#include "MainWindow.h"

MainWindow::MainWindow(QWidget* parent) :
	QMainWindow(parent) ,
	_devPx(devicePixelRatio())
{
	initMenuToolbar();
	initOCCTView();
	initSignals();
}

MainWindow::~MainWindow()
{
}

void MainWindow::initMenuToolbar()
{
	setWindowTitle("OCCTTutorial");
	setWindowIcon(QIcon(":/icons/icons/3dModel.png"));

	stb = new QStatusBar(this);
	this->setStatusBar(stb);
	lb_positionInfo = new QLabel(this);
	stb->addWidget(lb_positionInfo);

	tb_view = new QToolBar(this);
	//tb_view->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
	addToolBar(tb_view);

	act_hideAll = new QAction(QIcon(":/icons/icons/hideAll.png") , "hideAll" , this);
	act_hide = new QAction(QIcon(":/icons/icons/hide.png") , "hide" , this);
	act_fitAll = new QAction(QIcon(":/icons/icons/view-fullscreen.svg") , "fitAll" , this);
	act_axo = new QAction(QIcon(":/icons/icons/view-axonometric.svg") , "axo" , this);
	act_top = new QAction(QIcon(":/icons/icons/view-top.svg") , "top" , this);
	act_buttom = new QAction(QIcon(":/icons/icons/view-bottom.svg") , "buttom" , this);
	act_left = new QAction(QIcon(":/icons/icons/view-left.svg") , "left" , this);
	act_right = new QAction(QIcon(":/icons/icons/view-right.svg") , "right" , this);
	act_front = new QAction(QIcon(":/icons/icons/view-front.svg") , "front" , this);
	act_back = new QAction(QIcon(":/icons/icons/view-rear.svg") , "back" , this);
	act_shade = new QAction(QIcon(":/icons/icons/DrawStyleShaded.svg") , "shade" , this);
	act_wireframe = new QAction(QIcon(":/icons/icons/DrawStyleWireFrame.svg") , "wireframe" , this);
	act_perspective = new QAction(QIcon(":/icons/icons/perspective.png") , "perspective" , this);
	act_perspective->setCheckable(true);
	act_axis = new QAction(QIcon(":/icons/icons/axis.png") , "axis" , this);
	act_test = new QAction(QIcon(":/icons/icons/utilities-terminal.svg") , "test" , this);

	tb_view->addActions({ act_hideAll,act_hide,act_fitAll,act_axo,
	act_top,act_buttom,act_left,act_right,act_front,act_back });
	tb_view->addSeparator();
	tb_view->addActions({ act_shade,act_wireframe,act_perspective,act_axis,act_test });

	tb_style = new QToolBar(this);
	addToolBar(tb_style);
	addToolBarBreak();

	act_color = new QAction(QIcon(":/icons/icons/colors.svg") , "color" , this);
	act_material = new QAction(QIcon(":/icons/icons/Material.svg") , "material" , this);

	actgp_selectMode = new QActionGroup(this);
	actgp_selectMode->setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional);
	act_selectVertex = new QAction(QIcon(":/icons/icons/vertex-selection.svg") , "selectVertex" , this);
	act_selectVertex->setCheckable(true);
	act_selectEdge = new QAction(QIcon(":/icons/icons/edge-selection.svg") , "selectEdge" , this);
	act_selectEdge->setCheckable(true);
	act_selectFace = new QAction(QIcon(":/icons/icons/face-selection.svg") , "selectFace" , this);
	act_selectFace->setCheckable(true);
	lb_workArea = new QLabel(this);
	lb_workArea->setText("workArea: ");
	cbb_workArea = new QComboBox(this);
	cbb_workArea->addItems({ "None", "AISCustomPresentation","ModelingData","ModelingAlgorithms" ,
"DataExchange","Visualization", "MShape" });

	tb_style->addActions({ act_color,act_material });
	tb_style->addSeparator();
	tb_style->addActions({ act_selectVertex, act_selectEdge, act_selectFace });
	tb_style->addSeparator();
	tb_style->addWidget(lb_workArea);
	tb_style->addWidget(cbb_workArea);

	tb_aisCustom = new QToolBar(this);
	tb_aisCustom->setVisible(false);
	addToolBar(tb_aisCustom);
	tbs.push_back(tb_aisCustom);

	cbb_aisCustom = new QComboBox(this);
	cbb_aisCustom->addItems({ "Presentation builders", "Primitive arrays" ,"Primitive aspects" ,"Quadric builders" ,
		"Computing selection" ,"HighlightingSelectionOwner" ,"add arrow" });
	tb_aisCustom->addWidget(cbb_aisCustom);
	act_aisCustom = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_aisCustom->addAction(act_aisCustom);

	tb_ModelData = new QToolBar(this);
	tb_ModelData->setVisible(false);
	addToolBar(tb_ModelData);
	tbs.push_back(tb_ModelData);

	cbb_ModelData = new QComboBox(this);
	cbb_ModelData->addItems({ "Interpolations and Approximations","Direct Construction" ,"2D Geometry",
		"Points on Curves","Extrema","Topological types","Exploration" ,"Properties","Bounding boxes",
		"transform" });
	tb_ModelData->addWidget(cbb_ModelData);
	act_ModelData = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelData->addAction(act_ModelData);

	tb_ModelAlgorithm = new QToolBar(this);
	tb_ModelAlgorithm->setVisible(false);
	addToolBar(tb_ModelAlgorithm);
	tbs.push_back(tb_ModelAlgorithm);

	cbb_BRepBuilderAPI = new QComboBox(this);
	cbb_BRepBuilderAPI->addItems({ "Intersections","LinesAndCirclesFromConstraints","GeomFill_BSplineCurves","Projection","Edge",
		"Polygon","Face","Wire","Shell","Solid" });
	tb_ModelAlgorithm->addWidget(cbb_BRepBuilderAPI);
	act_BRepBuilderAPI = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_BRepBuilderAPI);

	cbb_BRepPrimAPI = new QComboBox(this);
	cbb_BRepPrimAPI->addItems({ "Making Primitives","Rotation object","Rotational Sweep","Prism",
		"Boolean Operations" ,"Getting normal for the face","History support" ,"Fillets and Chamfers" });
	tb_ModelAlgorithm->addWidget(cbb_BRepPrimAPI);
	act_BRepPrimAPI = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_BRepPrimAPI);

	cbb_BRepOffsetAPI = new QComboBox(this);
	cbb_BRepOffsetAPI->addItems({ "MakePipe","Offset computation" ,"Shelling","loft","PipeShell"});
	tb_ModelAlgorithm->addWidget(cbb_BRepOffsetAPI);
	act_BRepOffsetAPI = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_BRepOffsetAPI);

	cbb_Modification = new QComboBox(this);
	cbb_Modification->addItems({ "Transformation","Duplication","Sewing","BRepFeat_MakePrism" ,
		"BRepFeat_MakePipe" ,"3DModelDefeaturing","3DModelPeriodicity","drillExample" });
	tb_ModelAlgorithm->addWidget(cbb_Modification);
	act_Modification = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_Modification);

	cbb_Boolean = new QComboBox(this);
	cbb_Boolean->addItems({ "GFA","SPA","BOA","BRepAlgoAPI_Splitter" });
	tb_ModelAlgorithm->addWidget(cbb_Boolean);
	act_Boolean = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_Boolean);

	cbb_HLR = new QComboBox(this);
	cbb_HLR->addItems({ "HLRBRep_Algo" });
	tb_ModelAlgorithm->addWidget(cbb_HLR);
	act_HLR = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_ModelAlgorithm->addAction(act_HLR);

	tb_DataExchange = new QToolBar(this);
	tb_DataExchange->setVisible(false);
	addToolBar(tb_DataExchange);
	tbs.push_back(tb_DataExchange);

	cbb_DataExchange = new QComboBox(this);
	cbb_DataExchange->addItems({ "ExportBrep" ,"ImportBrep","ExportStep","ImportStep" ,"ExportIges","ImportIges",
		"ExportObj" ,"ImportObj" });
	tb_DataExchange->addWidget(cbb_DataExchange);
	act_DataExchange = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_DataExchange->addAction(act_DataExchange);

	tb_Visualization = new QToolBar(this);
	tb_Visualization->setVisible(false);
	addToolBar(tb_Visualization);
	tbs.push_back(tb_Visualization);

	cbb_ais = new QComboBox(this);
	cbb_ais->addItems({ "HLR","setLocation","ObjectHierarchy","Fitter","Selection/Capture" });
	tb_Visualization->addWidget(cbb_ais);
	act_ais = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_Visualization->addAction(act_ais);

	cbb_stdAis = new QComboBox(this);
	cbb_stdAis->addItems({ "Datum","AIS_PointCloud","Relations","Dimensions" });
	tb_Visualization->addWidget(cbb_stdAis);
	act_stdAis = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_Visualization->addAction(act_stdAis);

	cbb_Graphic3d = new QComboBox(this);
	cbb_Graphic3d->addItems({ "Primitive arrays","Text primitive","Clipping planes" });
	tb_Visualization->addWidget(cbb_Graphic3d);
	act_Graphic3d = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_Visualization->addAction(act_Graphic3d);

	tb_MShape = new QToolBar(this);
	tb_MShape->setVisible(false);
	addToolBar(tb_MShape);
	tbs.push_back(tb_MShape);

	cbb_MShape = new QComboBox(this);
	cbb_MShape->addItems({ "PipeFitting" });
	tb_MShape->addWidget(cbb_MShape);
	act_MShape = new QAction(QIcon(":/icons/icons/run.png") , "run" , this);
	tb_MShape->addAction(act_MShape);
}

void MainWindow::initOCCTView()
{
	myViewer = Viewer(V3d_XposYnegZpos);
	myContext = new AIS_InteractiveContext(myViewer);
	view_occt = new View(myContext , this);
	view_occt->installEventFilter(this);
	setCentralWidget(view_occt);
}

void MainWindow::initSignals()
{
	connect(view_occt , &View::selectionChanged , this , &MainWindow::processSelectChanged);
	connect(act_hideAll , &QAction::triggered , view_occt , &View::removeAll);
	connect(act_hide , &QAction::triggered , view_occt , &View::remove);
	connect(act_fitAll , &QAction::triggered , view_occt , &View::fitAll);
	connect(act_axo , &QAction::triggered , view_occt , &View::setAxo);
	connect(act_top , &QAction::triggered , view_occt , &View::setTop);
	connect(act_buttom , &QAction::triggered , view_occt , &View::setBottom);
	connect(act_left , &QAction::triggered , view_occt , &View::setLeft);
	connect(act_right , &QAction::triggered , view_occt , &View::setRight);
	connect(act_front , &QAction::triggered , view_occt , &View::setFront);
	connect(act_back , &QAction::triggered , view_occt , &View::setBack);

	connect(act_shade , &QAction::triggered , view_occt , &View::setShading);
	connect(act_wireframe , &QAction::triggered , view_occt , &View::setWireframe);
	connect(act_perspective , &QAction::triggered , this , &MainWindow::setPerspective);
	connect(act_axis , &QAction::triggered , view_occt , &View::setAxis);
	connect(act_test , &QAction::triggered , this , &MainWindow::test);

	connect(act_color , &QAction::triggered , this , &MainWindow::setColor);
	connect(act_selectVertex , &QAction::triggered , this , &MainWindow::setSelectMode);
	connect(act_selectEdge , &QAction::triggered , this , &MainWindow::setSelectMode);
	connect(act_selectFace , &QAction::triggered , this , &MainWindow::setSelectMode);

	connect(cbb_workArea , &QComboBox::currentIndexChanged , this , &MainWindow::setWorkArea);
	connect(act_aisCustom , &QAction::triggered , this , &MainWindow::runAisCustom);
	connect(act_ModelData , &QAction::triggered , this , &MainWindow::runModelData);
	connect(act_BRepBuilderAPI , &QAction::triggered , this , &MainWindow::runBRepBuilderAPI);
	connect(act_BRepPrimAPI , &QAction::triggered , this , &MainWindow::runBRepPrimAPI);
	connect(act_BRepOffsetAPI , &QAction::triggered , this , &MainWindow::runBRepOffsetAPI);
	connect(act_Modification , &QAction::triggered , this , &MainWindow::runModification);
	connect(act_Boolean , &QAction::triggered , this , &MainWindow::runBoolean);
	connect(act_HLR , &QAction::triggered , this , &MainWindow::runHLR);
	connect(act_DataExchange , &QAction::triggered , this , &MainWindow::runDataExchange);
	connect(act_ais , &QAction::triggered , this , &MainWindow::runAis);
	connect(act_stdAis , &QAction::triggered , this , &MainWindow::runStdAis);
	connect(act_Graphic3d , &QAction::triggered , this , &MainWindow::runGraphic3d);
	connect(act_MShape , &QAction::triggered , this , &MainWindow::runMShape);
}

void MainWindow::setPerspective(bool check)
{
	if (check)
		view_occt->setProjectionType(Graphic3d_Camera::Projection::Projection_Perspective);
	else
		view_occt->setProjectionType(Graphic3d_Camera::Projection::Projection_Orthographic);
}

void MainWindow::test()
{
	TopoDS_Shape box = BRepPrimAPI_MakeBox(20 , 20 , 20);
	//BRepFilletAPI_MakeFillet  MFFillet(box);
	//TopExp_Explorer  ex(box , TopAbs_EDGE);
	//double r = 2.;
	//int i = 0;
	//while (ex.More())
	//{
	//	if (i == 0)
	//	{
	//		MFFillet.Add(r , TopoDS::Edge(ex.Current()));
	//	}
	//	i++;
	//	ex.Next();
	//}
	//Handle(AIS_InteractiveObject) aisFillet = new MAisDemo(MFFillet.Shape());
	//myContext->Display(aisFillet , 1 , 0 , false);
	Handle(AIS_InteractiveObject) ais = new MAisDemo(box , true);
	myContext->Display(ais , 1 , 0 , false);
}

void MainWindow::setColor()
{
	QColor color = QColorDialog::getColor(Qt::white , this , "选择颜色");
	if (color.isValid())
	{
		myContext->InitSelected();
		Handle(AIS_InteractiveObject) selectedObject = myContext->SelectedInteractive();
		while (myContext->MoreSelected())
		{
			Handle(Prs3d_Drawer) drawer = selectedObject->Attributes();
			drawer->ShadingAspect()->SetColor(Quantity_Color(color.redF() ,
				color.greenF() ,
				color.blueF() ,
				Quantity_TOC_RGB));
			myContext->Redisplay(selectedObject , true);

			myContext->NextSelected();
		}
	}
}

void MainWindow::setSelectMode()
{
	bool checkVertex = act_selectVertex->isChecked();
	bool checkEdge = act_selectEdge->isChecked();
	bool checkFace = act_selectFace->isChecked();

	myContext->Deactivate();
	if (checkVertex && !checkEdge && !checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_VERTEX));
	}
	else if (!checkVertex && checkEdge && !checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE));
	}
	else if (!checkVertex && !checkEdge && checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_FACE));
	}
	else if (checkVertex && checkEdge && !checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_VERTEX));
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE));
	}
	else if (checkVertex && !checkEdge && checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_VERTEX));
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_FACE));
	}
	else if (!checkVertex && checkEdge && checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE));
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_FACE));
	}
	else if (checkVertex && checkEdge && checkFace)
	{
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_VERTEX));
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_EDGE));
		myContext->Activate(AIS_Shape::SelectionMode(TopAbs_FACE));
	}
	else
	{
		myContext->Activate(0);
	}
}

void MainWindow::setWorkArea(int index)
{
	if (index == 0)
	{
		for (int i = 0; i < tbs.size(); ++i)
		{
			tbs[i]->setVisible(false);
		}
	}
	else
	{
		for (int i = 0; i < tbs.size(); ++i)
		{
			if (i == index - 1)
			{
				tbs[i]->setVisible(true);
			}
			else
			{
				tbs[i]->setVisible(false);
			}
		}
	}
}

void MainWindow::processSelectChanged()
{
	myContext->InitSelected();

	TopoDS_Shape selShape = myContext->SelectedShape();
	if (!selShape.IsNull() && selShape.ShapeType() == TopAbs_EDGE)
	{
		//TopoDS_Edge edge = TopoDS::Edge(selShape);

		//Handle(AIS_InteractiveObject) selected = myContext->SelectedInteractive();
		//Handle(MAisDemo) sel = Handle(MAisDemo)::DownCast(selected);
		//TopoDS_Shape aShape = sel->Shape();
		//
		//BRepFilletAPI_MakeFillet  MFFillet(aShape, ChFi3d_Polynomial);
		//TopExp_Explorer  ex(aShape , TopAbs_EDGE);
		//double r = 2.;
		//MFFillet.Add(r , edge);
		//Handle(AIS_InteractiveObject) aisFillet = new MAisDemo(MFFillet.Shape());

		//myContext->Remove(selected , false);
		//myContext->Display(aisFillet , 1 , 0 , true);
		//myContext->Activate(aisFillet , MAisDemo::SelectionMode(TopAbs_EDGE));
	}
}

void MainWindow::runAisCustom()
{
	if (cbb_aisCustom->currentText() == "Presentation builders")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject0(aShape);
		myContext->Display(ais , 0 , 0 , false);
		myContext->HilightWithColor(ais , ais->HilightAttributes() , false);
	}
	else if (cbb_aisCustom->currentText() == "Primitive arrays")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject1(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_aisCustom->currentText() == "Primitive aspects")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject2(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_aisCustom->currentText() == "Quadric builders")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject3(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_aisCustom->currentText() == "Computing selection")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject4(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_aisCustom->currentText() == "HighlightingSelectionOwner")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject5(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_aisCustom->currentText() == "add arrow")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(100.0 , 100.0);
		Handle(AIS_InteractiveObject) ais = new MAisObject6(aShape);
		myContext->Display(ais , 0 , 0 , false);
	}
	view_occt->fitAll();
}

void MainWindow::runModelData()
{
	if (cbb_ModelData->currentText() == "Interpolations and Approximations")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0),gp_Pnt(200 , 200 , 0) };
		Handle(TColgp_HArray1OfPnt) ps = new TColgp_HArray1OfPnt(1 , 4);
		int i = 1;
		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new AIS_Shape(aVertex);
			myContext->Display(aisVertex , false);
			ps->SetValue(i , p);
			++i;
		}

		// 插值法不是完全通过构造点
		GeomAPI_Interpolate Interp(ps , false , Precision::Confusion());
		Interp.Perform();
		Handle(Geom_BSplineCurve) C = Interp.Curve();
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new AIS_Shape(aEdge);
		myContext->Display(ais , false);

		auto psArr = ps->Array1();
		GeomAPI_PointsToBSpline Approx(psArr);
		Handle(Geom_BSplineCurve) CApprox = Approx.Curve();
		CApprox->Translate(gp_Vec(0 , 0 , 100));
		TopoDS_Edge aEdgeApprox = BRepBuilderAPI_MakeEdge(CApprox);
		Handle(AIS_InteractiveObject) aisApprox = new AIS_Shape(aEdgeApprox);
		myContext->Display(aisApprox , false);

		// 只有首位两点保证通过
		Handle(Geom_BezierCurve) CBezier = new Geom_BezierCurve(psArr);
		CBezier->Translate(gp_Vec(0 , 0 , 200));
		TopoDS_Edge aEdgeBezier = BRepBuilderAPI_MakeEdge(CBezier);
		Handle(AIS_InteractiveObject) aisBezier = new AIS_Shape(aEdgeBezier);
		myContext->Display(aisBezier , false);

		// 控制斜率
		Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1 , 2);
		points->SetValue(1 , gp_Pnt(0 , 0 , 0));
		points->SetValue(2 , gp_Pnt(200 , 0 , 0));

		GeomAPI_Interpolate interpolator(points , false , Precision::Confusion());
		interpolator.Load(gp_Vec(0 , 1 , 0) , gp_Vec(0 , -1 , 0));
		interpolator.Perform();

		Handle(Geom_BSplineCurve) cir = interpolator.Curve();
		TopoDS_Edge aEdgeCir = BRepBuilderAPI_MakeEdge(cir);
		Handle(AIS_InteractiveObject) aisCir = new AIS_Shape(aEdgeCir);
		myContext->Display(aisCir , false);
	}
	else if (cbb_ModelData->currentText() == "Direct Construction")
	{
		gp_Pnt pnt0 = gp_Pnt(0 , 0 , 0);
		gp_Pnt pnt1 = gp_Pnt(0 , 100 , 0);
		gp_Pnt pnt2 = gp_Pnt(100 , 150 , 0);
		TopoDS_Vertex aVertex0 = BRepBuilderAPI_MakeVertex(pnt0);
		TopoDS_Vertex aVertex1 = BRepBuilderAPI_MakeVertex(pnt1);
		TopoDS_Vertex aVertex2 = BRepBuilderAPI_MakeVertex(pnt2);

		Handle(AIS_InteractiveObject) aisVertex0 = new AIS_Shape(aVertex0);
		Handle(AIS_InteractiveObject) aisVertex1 = new AIS_Shape(aVertex1);
		Handle(AIS_InteractiveObject) aisVertex2 = new AIS_Shape(aVertex2);
		myContext->Display(aisVertex0 , false);
		myContext->Display(aisVertex1 , false);
		myContext->Display(aisVertex2 , false);

		gce_MakeCirc MC(pnt0 , pnt1 , pnt2);
		if (MC.IsDone())
		{
			const gp_Circ& C = MC.Value();
			TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
			Handle(AIS_InteractiveObject) ais = new AIS_Shape(aEdge);
			myContext->Display(ais , false);
		}
	}
	else if (cbb_ModelData->currentText() == "2D Geometry")
	{
		gp_Pnt aStart = gp_Pnt(0 , 0 , 0);
		gp_Pnt aEnd = gp_Pnt(200 , 200 , 200);
		TopoDS_Edge aPath = BRepBuilderAPI_MakeEdge(aStart , aEnd);
		Handle(AIS_InteractiveObject) aisPath = new MAisDemo(aPath);
		myContext->Display(aisPath , 1 , 0 , false);

		double myWidth = 100;
		double myHeight = 50;

		gp_Vec vec = gp_Vec(aStart , aEnd);

		// 设置平面X方向平行于OXY
		gp_Vec vecX = vec.Crossed(gp_Vec(0 , 0 , 1));
		gp_Ax3 ax3 = gp_Ax3(aStart , vec , vecX);
		Handle(Geom_Surface) surf = new Geom_Plane(ax3);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(surf , -200 , 200 , -100 , 100 , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		aisFace->SetTransparency(0.5);
		myContext->Display(aisFace , 1 , 0 , false);

		gp_Pnt2d pnt2d1 = gp_Pnt2d(-myWidth / 2 , myHeight / 2);
		gp_Pnt2d pnt2d2 = gp_Pnt2d(myWidth / 2 , myHeight / 2);
		gp_Pnt2d pnt2d3 = gp_Pnt2d(myWidth / 2 , -myHeight / 2);
		gp_Pnt2d pnt2d4 = gp_Pnt2d(-myWidth / 2 , -myHeight / 2);
		Handle(Geom2d_Line) geom2dLin1 = GCE2d_MakeLine(pnt2d1 , pnt2d2).Value();
		Handle(Geom2d_Line) geom2dLin2 = GCE2d_MakeLine(pnt2d2 , pnt2d3).Value();
		Handle(Geom2d_Line) geom2dLin3 = GCE2d_MakeLine(pnt2d3 , pnt2d4).Value();
		Handle(Geom2d_Line) geom2dLin4 = GCE2d_MakeLine(pnt2d4 , pnt2d1).Value();

		BRepBuilderAPI_MakeWire MW;
		MW.Add(BRepBuilderAPI_MakeEdge(geom2dLin1 , surf , 0 , myWidth));
		MW.Add(BRepBuilderAPI_MakeEdge(geom2dLin2 , surf , 0 , myHeight));
		MW.Add(BRepBuilderAPI_MakeEdge(geom2dLin3 , surf , 0 , myWidth));
		MW.Add(BRepBuilderAPI_MakeEdge(geom2dLin4 , surf , 0 , myHeight));
		TopoDS_Wire myProfile = MW;
		BRepLib::BuildCurves3d(myProfile); // 没有此步骤后面无法扫掠
		Handle(AIS_InteractiveObject) aisProfile = new MAisDemo(myProfile);
		myContext->Display(aisProfile , 1 , 0 , false);


		TopoDS_Wire myPath = BRepBuilderAPI_MakeWire(aPath);
		TopoDS_Shape myShape = BRepOffsetAPI_MakePipe(myPath , myProfile);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(myShape);
		myContext->Display(ais , 1 , 0 , false);

		//gp_Pnt pnt1 , pnt2 , pnt3 , pnt4;
		//surf->D0(-myWidth / 2 , myHeight / 2 , pnt1);
		//surf->D0(myWidth / 2 , myHeight / 2 , pnt2);
		//surf->D0(myWidth / 2 , -myHeight / 2 , pnt3);
		//surf->D0(-myWidth / 2 , -myHeight / 2 , pnt4);
		//BRepBuilderAPI_MakeWire MW;
		//MW.Add(BRepBuilderAPI_MakeEdge(pnt1 , pnt2));
		//MW.Add(BRepBuilderAPI_MakeEdge(pnt2 , pnt3));
		//MW.Add(BRepBuilderAPI_MakeEdge(pnt3 , pnt4));
		//MW.Add(BRepBuilderAPI_MakeEdge(pnt4 , pnt1));
		//TopoDS_Wire myProfile = MW;

		//Handle(AIS_InteractiveObject) aisProfile = new MAisDemo(myProfile);
		//myContext->Display(aisProfile , 1 , 0 , false);

		//TopoDS_Wire myPath = BRepBuilderAPI_MakeWire(aPath);
		//TopoDS_Shape myShape = BRepOffsetAPI_MakePipe(myPath , myProfile);
		//Handle(AIS_InteractiveObject) ais = new MAisDemo(myShape);
		//myContext->Display(ais , 1 , 0 , false);
	}
	else if (cbb_ModelData->currentText() == "Points on Curves")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0),gp_Pnt(200 , 200 , 0) };

		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new AIS_Shape(aVertex);
			myContext->Display(aisVertex , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new AIS_Shape(aEdge);
		myContext->Display(ais , false);

		std::cout << C->FirstParameter() << std::endl;
		std::cout << C->LastParameter() << std::endl;
		gp_Pnt p1 , p2;
		C->D0(C->FirstParameter() , p1);
		C->D0(C->LastParameter() , p2);
		std::cout << p1 << std::endl;
		std::cout << p2 << std::endl;

		GeomAdaptor_Curve adp(C);
		GCPnts_AbscissaPoint myAlgo(adp , 100 , 0);
		std::cout << myAlgo.Parameter() << std::endl;
		std::cout << GCPnts_AbscissaPoint::Length(adp) << std::endl;
	}
	else if (cbb_ModelData->currentText() == "Extrema")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0),gp_Pnt(200 , 200 , 0) };

		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new AIS_Shape(aVertex);
			myContext->Display(aisVertex , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new AIS_Shape(aEdge);
		myContext->Display(ais , false);

		gp_Pnt aPnt = gp_Pnt(0 , 100 , 100);
		TopoDS_Vertex aVertexS = BRepBuilderAPI_MakeVertex(aPnt);
		Handle(AIS_InteractiveObject) aisVertexS = new AIS_Shape(aVertexS);
		myContext->Display(aisVertexS , false);
		GeomAPI_ProjectPointOnCurve project(aPnt , C);

		std::cout << project.LowerDistance() << std::endl;
		std::cout << project.Point(1) << std::endl;
	}
	else if (cbb_ModelData->currentText() == "Topological types")
	{
		TopoDS_Shape aShape = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 0 , 200) , gp_Pnt(0 , 0 , 400));
		TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(100 , 100 , 100);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		myContext->Display(ais , 1 , 0 , false);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aShape1);
		myContext->Display(ais1 , 1 , 0 , false);

		TopAbs::Print(aShape.ShapeType() , std::cout);
		std::cout << std::endl;

		bool check = (aShape.ShapeType() == TopAbs_EDGE);
		std::cout << check << std::endl;

		TopAbs::Print(aShape1.ShapeType() , std::cout);
		std::cout << std::endl;

		TopoDS_Solid V = TopoDS::Solid(aShape1);
		TopAbs::Print(V.ShapeType() , std::cout);
	}
	else if (cbb_ModelData->currentText() == "Exploration")
	{
		TopoDS_Shape aShape = BRepPrimAPI_MakeBox(100 , 100 , 100);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		myContext->Display(ais , 1 , 0 , false);

		// 此方法所有edge都会参与迭代，若考虑共享，需使用TopExp::MapShapes方法
		// demo可参考ModelingAlgorithms/Fillets and Chamfers最后的示例

		for (TopExp_Explorer Ex(aShape , TopAbs_EDGE); Ex.More(); Ex.Next())
		{
			TopAbs::Print(Ex.Current().ShapeType() , std::cout);
			std::cout << std::endl;
		}

	}
	else if (cbb_ModelData->currentText() == "Properties")
	{
		TopoDS_Shape aShape = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 0 , 200) , gp_Pnt(0 , 0 , 400));
		TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(100 , 100 , 100);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		myContext->Display(ais , 1 , 0 , false);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aShape1);
		myContext->Display(ais1 , 1 , 0 , false);

		GProp_GProps props;
		BRepGProp::LinearProperties(aShape , props);
		int length = props.Mass();
		std::cout << length << std::endl;
		gp_Pnt center = props.CentreOfMass();
		std::cout << center << std::endl;

		gp_Circ cir = gp_Circ(gp_Ax2(gp_Pnt(0 , 50 , 0) , gp_Dir(0 , 0 , 1)) , 50);
		TopoDS_Edge aCirc = BRepBuilderAPI_MakeEdge(cir , 0 , M_PI / 2);
		Handle(AIS_InteractiveObject) aisCirc = new MAisDemo(aCirc);
		myContext->Display(aisCirc , false);

		// 此方法适合线性的算法，不适合圆弧
		GProp_GProps propsCirc;
		BRepGProp::LinearProperties(aCirc , propsCirc);
		int lengthCirc = propsCirc.Mass();
		std::cout << lengthCirc << std::endl;
		gp_Pnt centreCirc = propsCirc.CentreOfMass();
		std::cout << centreCirc << std::endl;
		TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(centreCirc);
		Handle(AIS_InteractiveObject) aisVertex = new MAisDemo(aVertex);
		myContext->Display(aisVertex , false);

	}
	else if (cbb_ModelData->currentText() == "Bounding boxes")
	{
		TopoDS_Edge aShape = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 0 , 0) , gp_Pnt(0 , 100 , 100));
		TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(gp_Ax2(gp_Pnt(0 , 200 , 0) , gp_Dir(0 , 0 , 1)) , 100 , 100 , 100);
		Handle(AIS_InteractiveObject) ais = new MAisObject9(aShape);
		Handle(AIS_InteractiveObject) ais1 = new MAisObject9(aShape1);
		myContext->Display(ais , 1 , 0 , false);
		myContext->Display(ais1 , 1 , 0 , false);
		gp_Circ cir = gp_Circ(gp_Ax2(gp_Pnt(0 , 50 , 0) , gp_Dir(0 , 0 , 1)) , 50);
		TopoDS_Edge aCirc = BRepBuilderAPI_MakeEdge(cir , 0 , M_PI / 2);
		Handle(AIS_InteractiveObject) aisCirc = new MAisObject9(aCirc);
		myContext->Display(aisCirc , 1 , 0 , false);
	}
	else if (cbb_ModelData->currentText() == "transform")
	{
		gp_Pnt aPnt = gp_Pnt(0 , 0 , 0);
		TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(aPnt);
		Handle(AIS_InteractiveObject) aisPnt = new MAisDemo(aVertex);
		myContext->Display(aisPnt , 1 , 0 , false);

		gp_Pnt aPnt1 = aPnt.Translated(gp_Pnt(10 , 0 , 0) , gp_Pnt(30 , 0 , 0));
		TopoDS_Vertex aVertex1 = BRepBuilderAPI_MakeVertex(aPnt1);
		Handle(AIS_InteractiveObject) aisPnt1 = new MAisDemo(aVertex1);
		myContext->Display(aisPnt1 , 1 , 0 , false);

		gp_Trsf T;
		gp_Vec vec = gp_Vec(0 , 20 , 0);
		std::cout << vec.Magnitude() << std::endl;
		T.SetTranslation(vec);
		gp_Pnt aPnt2 = aPnt.Transformed(T);
		TopoDS_Vertex aVertex2 = BRepBuilderAPI_MakeVertex(aPnt2);
		Handle(AIS_InteractiveObject) aisPnt2 = new MAisDemo(aVertex2);
		myContext->Display(aisPnt2 , 1 , 0 , false);

		gp_Circ cir = gp_Circ(gp_Ax2(gp_Pnt(0 , 50 , 0) , gp_Dir(0 , 0 , 1)) , 50);
		TopoDS_Edge aCirc = BRepBuilderAPI_MakeEdge(cir , 0 , M_PI / 2);
		Handle(AIS_InteractiveObject) aisCirc = new MAisDemo(aCirc);
		myContext->Display(aisCirc , 1 , 0 , false);

		gp_Pln aPln = gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(1 , 0 , 0));
		Handle(Geom_Plane) geomPln = new Geom_Plane(aPln);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(geomPln , -100 , 100 , -200 , 200 , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		T.SetTranslation(gp_Vec(200 , 0 , 0));
		BRepBuilderAPI_Transform trsf(aFace , T);
		Handle(AIS_InteractiveObject) aisFace1 = new MAisDemo(trsf.Shape());
		myContext->Display(aisFace1 , 1 , 0 , false);
	}

	view_occt->fitAll();
}

void MainWindow::runBRepBuilderAPI()
{
	if (cbb_BRepBuilderAPI->currentText() == "Intersections")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0),gp_Pnt(200 , 200 , 0) };

		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new MAisDemo(aVertex);
			myContext->Display(aisVertex , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aEdge);
		myContext->Display(ais , 1 , 0 , false);

		gp_Pln pln = gp_Pln(gp_Pnt(100 , 0 , 0) , gp_Dir(1 , 0 , 0));
		Handle(Geom_Surface) S = new Geom_Plane(pln);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(S , -200 , 200 , -200 , 200 , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		GeomAPI_IntCS Intersector(C , S);
		if (Intersector.NbPoints() != 0)
		{
			std::cout << Intersector.Point(1) << std::endl;
		}
		else
			std::cout << "empty" << std::endl;

	}
	if (cbb_BRepBuilderAPI->currentText() == "LinesAndCirclesFromConstraints")
	{
		gp_Lin2d C1 = gp_Lin2d(gp_Pnt2d(0 , 0) , gp_Dir2d(1 , 0));
		gp_Lin2d C2 = gp_Lin2d(gp_Pnt2d(0 , 10) , gp_Dir2d(1 , 1));

		gp_Pln pln = gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		Handle(Geom_Surface) surf = new Geom_Plane(pln);

		Handle(Geom2d_Curve) aL1 = new Geom2d_Line(C1);
		Handle(Geom2d_Curve) aC1 = new Geom2d_TrimmedCurve(aL1 , -20 , 20);
		TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(aC1 , surf);

		Handle(Geom2d_Curve) aL2 = new Geom2d_Line(C2);
		Handle(Geom2d_Curve) aC2 = new Geom2d_TrimmedCurve(aL2 , -20 , 20);
		TopoDS_Edge aEdge2 = BRepBuilderAPI_MakeEdge(aC2 , surf);

		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aEdge1);
		myContext->Display(ais1 , 1 , 0 , false);
		Handle(AIS_InteractiveObject) ais2 = new MAisDemo(aEdge2);
		myContext->Display(ais2 , 1 , 0 , false);

		GccAna_Circ2d2TanRad Solver(GccEnt::Enclosed(C1) , GccEnt::Outside(C2) , 1 , 0);
		std::cout << Solver.NbSolutions() << std::endl;

		gp_Circ2d c = Solver.ThisSolution(1);

		Handle(Geom2d_Curve) aCir = new Geom2d_Circle(c);
		TopoDS_Edge aEdge3 = BRepBuilderAPI_MakeEdge(aCir , surf);
		Handle(AIS_InteractiveObject) ais3 = new MAisDemo(aEdge3);
		myContext->Display(ais3 , 1 , 0 , false);

	}
	else if (cbb_BRepBuilderAPI->currentText() == "GeomFill_BSplineCurves")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0) ,gp_Pnt(200 , 200 , 0) };
		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new MAisDemo(aVertex);
			myContext->Display(aisVertex , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aEdge);
		myContext->Display(ais , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 0 , 500));
		Handle(Geom_Geometry) geom = C->Transformed(T);
		Handle(Geom_BSplineCurve) C1 = Handle(Geom_BSplineCurve)::DownCast(geom);
		TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(C1);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aEdge1);
		myContext->Display(ais1 , 1 , 0 , false);

		// 此方法的curve必须开放
		GeomFill_BSplineCurves fill(C , C1 , GeomFill_StretchStyle);
		Handle(Geom_Surface) suf = fill.Surface();
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(suf , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Projection")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0) ,gp_Pnt(200 , 200 , 0) };
		for (auto p : pnts)
		{
			TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisVertex = new MAisDemo(aVertex);
			myContext->Display(aisVertex , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aEdge);
		myContext->Display(ais , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 0 , 500));
		Handle(Geom_Geometry) geom = C->Transformed(T);
		Handle(Geom_BSplineCurve) C1 = Handle(Geom_BSplineCurve)::DownCast(geom);
		TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(C1);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aEdge1);
		myContext->Display(ais1 , 1 , 0 , false);

		// 此方法的curve必须开放
		GeomFill_BSplineCurves fill(C , C1 , GeomFill_StretchStyle);
		Handle(Geom_Surface) suf = fill.Surface();
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(suf , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		gp_Pnt pnt = gp_Pnt(50 , 50 , 100);
		TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex(pnt);
		Handle(AIS_InteractiveObject) aisPnt = new MAisDemo(aVertex);
		myContext->Display(aisPnt , false);

		GeomAPI_ProjectPointOnSurf Proj(pnt , suf);

		int NumSolutions = Proj.NbPoints();
		std::cout << NumSolutions << std::endl;

		for (int i = 1; i <= NumSolutions; ++i)
		{
			gp_Pnt pntProj = Proj.Point(i);
			std::cout << "Project point: " << pntProj << std::endl;
			TopoDS_Vertex aVertexProj = BRepBuilderAPI_MakeVertex(pntProj);
			Handle(AIS_InteractiveObject) aisProj = new MAisDemo(aVertexProj);
			myContext->Display(aisProj , false);

			TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(aVertex , aVertexProj);
			Handle(AIS_InteractiveObject) aisEdgeProj = new MAisDemo(aEdge);
			myContext->Display(aisEdgeProj , false);

			Standard_Real U , V;
			Proj.Parameters(i , U , V);
			std::cout << "U: " << U << ", V: " << V << std::endl;

			gp_Pnt pntRet;
			//suf->D0(U , V , pntRet); 
			pntRet = suf->Value(U , V);// 同上
			std::cout << "D0: " << pntRet << std::endl;

			double D = Proj.Distance(i);
			std::cout << "distance: " << D << std::endl;
		}
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Edge")
	{
		gp_Pnt pnt1(100 , 0 , 0);
		gp_Pnt pnt2(200 , 0 , 0);

		TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(pnt1);
		TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(pnt2);
		Handle(AIS_InteractiveObject) aisV1 = new MAisDemo(V1);
		myContext->Display(aisV1 , 1 , 0 , false);
		Handle(AIS_InteractiveObject) aisV2 = new MAisDemo(V2);
		myContext->Display(aisV2 , 1 , 0 , false);

		Handle(Geom_TrimmedCurve) C = GC_MakeSegment(pnt1 , pnt2);
		double p1 = C->FirstParameter();
		double p2 = C->LastParameter(); // 长度
		std::cout << "first: " << p1 << ",last: " << p2 << std::endl;
		gp_Pnt pntMid = C->Value(p2 * 0.5);
		std::cout << "pntMid: " << pntMid << std::endl;
		TopoDS_Edge E = BRepBuilderAPI_MakeEdge(C , p1 , p2);
		//TopoDS_Edge E = BRepBuilderAPI_MakeEdge(pnt1 , pnt2);

		Handle(AIS_InteractiveObject) aisEdge = new MAisDemo(E);
		myContext->Display(aisEdge , 1 , 0 , false);

		gp_Ax2 Origin = gp::XOY();
		//0:X轴，M_PI:-X轴
		BRepBuilderAPI_MakeEdge ME(gp_Circ(Origin , 100) , 0 , M_PI);
		Handle(AIS_InteractiveObject) aisME = new MAisDemo(ME);
		myContext->Display(aisME , 1 , 0 , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Polygon")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100 , 0 , 0) ,gp_Pnt(200 , 200 , 0) ,
			gp_Pnt(300 , 100 , 0) ,gp_Pnt(0 , 500 , 300) };

		BRepBuilderAPI_MakePolygon MP;
		for (auto p : pnts)
		{
			MP.Add(p);
		}
		//MP.Close();
		TopoDS_Wire aWire = MP.Wire();
		Handle(AIS_InteractiveObject) aisWire = new MAisDemo(aWire);
		myContext->Display(aisWire , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Face")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(0 , 100 , 0) ,gp_Pnt(100 , 150 , 0) ,gp_Pnt(200 , 200 , 0) };
		for (auto p : pnts)
		{
			TopoDS_Vertex aPnt = BRepBuilderAPI_MakeVertex(p);
			Handle(AIS_InteractiveObject) aisPnt = new MAisDemo(aPnt);
			myContext->Display(aisPnt , false);
		}

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aEdge);
		myContext->Display(ais , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 0 , 500));
		Handle(Geom_Geometry) geom = C->Transformed(T);
		Handle(Geom_BSplineCurve) C1 = Handle(Geom_BSplineCurve)::DownCast(geom);
		TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(C1);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aEdge1);
		myContext->Display(ais1 , 1 , 0 , false);

		// 此方法的curve必须开放
		GeomFill_BSplineCurves fill(C , C1 , GeomFill_StretchStyle);
		Handle(Geom_Surface) suf = fill.Surface();
		//TopoDS_Face aFace = BRepBuilderAPI_MakeFace(suf , 0);

		double umin , umax , vmin , vmax;
		suf->Bounds(umin , umax , vmin , vmax);
		std::cout << "umin: " << umin << ",umax: " << umax << ",vmin: " << vmin << ",vmax: " << vmax << std::endl;
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(suf , umax * 0.2 , umax * 0.5 , vmin , vmax * 0.5 , 0);

		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Wire")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100,0,0), gp_Pnt(200,0,0), gp_Pnt(150,100,0), gp_Pnt(500,200,0) };

		BRepBuilderAPI_MakeWire MW;
		for (int i = 0; i < pnts.size() - 1; ++i)
		{
			// 已有Edge必须有点可使新Edge首尾相连
			//if (i % 2 == 0)
			//{
			//	TopoDS_Edge E = BRepBuilderAPI_MakeEdge(pnts[i] , pnts[i + 1]);
			//	Handle(AIS_InteractiveObject) aisEdge = new AIS_Shape(E);
			//	myContext->Display(aisEdge , 1 , 0 , false);
			//	MW.Add(E);
			//}
			TopoDS_Edge E = BRepBuilderAPI_MakeEdge(pnts[i] , pnts[i + 1]);
			MW.Add(E);
		}
		TopoDS_Wire W = MW;
		Handle(AIS_InteractiveObject) aisWire = new AIS_Shape(W);
		myContext->Display(aisWire , 1 , 0 , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Shell")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100,0,0), gp_Pnt(200,100,0), gp_Pnt(250,300,0), gp_Pnt(500,400,0) };
		std::vector<gp_Pnt> pnts1 = { gp_Pnt(0,0,300), gp_Pnt(0,100,300), gp_Pnt(200,200,300), gp_Pnt(300,250,300) };

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		Handle(Geom_BSplineCurve) C1 = createBSplineCurve(pnts1);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(500 , 0 , 0));
		Handle(Geom_Geometry) geom = C->Transformed(T);
		Handle(Geom_BSplineCurve) C2 = Handle(Geom_BSplineCurve)::DownCast(geom);

		T.SetTranslation(gp_Vec(500 , 0 , 300));
		Handle(Geom_Geometry) geom1 = C1->Transformed(T);
		Handle(Geom_BSplineCurve) C3 = Handle(Geom_BSplineCurve)::DownCast(geom1);

		std::vector<Handle(Geom_BSplineCurve)> curves = { C,C1,C3,C2,C };
		//for (int i = 0; i < curves.size() - 1; ++i)
		//{
		//	GeomFill_BSplineCurves fill(curves[i] , curves[i + 1] , GeomFill_StretchStyle);
		//	Handle(Geom_Surface) suf = fill.Surface();
		//	// MakeShell只能一个面一个面的构造
		//	TopoDS_Shell shell = BRepBuilderAPI_MakeShell(suf);

		//	Handle(AIS_InteractiveObject) aisshell = new MAisDemo(shell);
		//	myContext->Display(aisshell , 1 , 0 , false);
		//}

		// 此方法可添加多个面
		TopoDS_Shell shell;
		BRep_Builder builder;
		builder.MakeShell(shell);
		for (int i = 0; i < curves.size() - 1; ++i)
		{
			GeomFill_BSplineCurves fill(curves[i] , curves[i + 1] , GeomFill_StretchStyle);
			Handle(Geom_Surface) suf = fill.Surface();

			TopoDS_Face face = BRepBuilderAPI_MakeFace(suf , 0);
			builder.Add(shell , face);
		}
		TopAbs::Print(shell.ShapeType() , std::cout);
		Handle(AIS_InteractiveObject) aisshell = new MAisDemo(shell);
		myContext->Display(aisshell , 1 , 0 , false);
	}
	else if (cbb_BRepBuilderAPI->currentText() == "Solid")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100,0,0), gp_Pnt(200,100,0), gp_Pnt(250,300,0), gp_Pnt(500,400,0) };
		std::vector<gp_Pnt> pnts1 = { gp_Pnt(0,0,300), gp_Pnt(0,100,300), gp_Pnt(200,200,300), gp_Pnt(300,250,300) };

		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		Handle(Geom_BSplineCurve) C1 = createBSplineCurve(pnts1);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(500 , 0 , 0));
		Handle(Geom_Geometry) geom = C->Transformed(T);
		Handle(Geom_BSplineCurve) C2 = Handle(Geom_BSplineCurve)::DownCast(geom);

		T.SetTranslation(gp_Vec(500 , 0 , 300));
		Handle(Geom_Geometry) geom1 = C1->Transformed(T);
		Handle(Geom_BSplineCurve) C3 = Handle(Geom_BSplineCurve)::DownCast(geom1);

		std::vector<Handle(Geom_BSplineCurve)> curves = { C,C1,C3,C2,C };
		BRepBuilderAPI_MakeSolid solidBuilder;
		for (int i = 0; i < curves.size() - 1; ++i)
		{
			GeomFill_BSplineCurves fill(curves[i] , curves[i + 1] , GeomFill_StretchStyle);
			Handle(Geom_Surface) suf = fill.Surface();
			TopoDS_Shell shell = BRepBuilderAPI_MakeShell(suf);
			TopAbs::Print(shell.ShapeType() , std::cout);
			std::cout << std::endl;
			solidBuilder.Add(shell);
		}
		Handle(AIS_InteractiveObject) aisSolid = new MAisDemo(solidBuilder.Solid());
		TopAbs::Print(solidBuilder.Solid().ShapeType() , std::cout);
		std::cout << std::endl;
		myContext->Display(aisSolid , 1 , 0 , false);
	}

	view_occt->fitAll();
}

void MainWindow::runBRepPrimAPI()
{
	if (cbb_BRepPrimAPI->currentText() == "Making Primitives")
	{
		TopoDS_Shape Box = BRepPrimAPI_MakeBox(10 , 20 , 30);
		Handle(AIS_InteractiveObject) aisBox = new MAisDemo(Box);
		myContext->Display(aisBox , 1 , 0 , false);

		TopoDS_Shape Cone = BRepPrimAPI_MakeCone(10 , 5 , 30, M_PI * 2);
		Handle(AIS_InteractiveObject) aisCone = new MAisDemo(Cone);
		myContext->Display(aisCone , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 50 , 0));
		aisCone->SetLocalTransformation(T);

		TopoDS_Shape Cylinder = BRepPrimAPI_MakeCylinder(10 , 30 , M_PI * 2);
		Handle(AIS_InteractiveObject) aisCylinder = new MAisDemo(Cylinder);
		myContext->Display(aisCylinder , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 100 , 0));
		aisCylinder->SetLocalTransformation(T);

		TopoDS_Shape Sphere = BRepPrimAPI_MakeSphere(10 );
		Handle(AIS_InteractiveObject) aisSphere = new MAisDemo(Sphere);
		myContext->Display(aisSphere , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 150 , 0));
		aisSphere->SetLocalTransformation(T);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Rotation object")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100,0,100), gp_Pnt(200,0,200), gp_Pnt(150,0,300), gp_Pnt(400,0,500) };
		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		TopoDS_Shape aEdge = BRepBuilderAPI_MakeEdge(C);
		Handle(AIS_InteractiveObject) aisEdge = new MAisDemo(aEdge);
		myContext->Display(aisEdge , 1 , 0 , false);
		// 只支持Z轴,自动封口，曲线斜率有一定要求
		BRepPrimAPI_MakeRevolution revolutionBuilder(C , M_PI / 2);
		TopoDS_Shape aShape = revolutionBuilder.Solid();
		Handle(AIS_InteractiveObject) aisShape = new MAisDemo(aShape);
		myContext->Display(aisShape , 1 , 0 , false);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Rotational Sweep")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(300,0,100), gp_Pnt(400,0,200), gp_Pnt(350,0,300),
			gp_Pnt(300,0,500) };
		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		C->SetPeriodic();
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(aEdge);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		gp_Ax1 axis(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		TopoDS_Shape R1 = BRepPrimAPI_MakeRevol(aFace , axis , M_PI / 2);
		//TopoDS_Shape R1 = BRepPrimAPI_MakeRevol(aFace , gp::OZ() , M_PI / 2);

		Handle(AIS_InteractiveObject) aisRotation = new MAisDemo(R1);
		myContext->Display(aisRotation , 1 , 0 , false);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Prism")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(100,100,0), gp_Pnt(200,200,0), gp_Pnt(150,300,0), gp_Pnt(-400,500,0) };
		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts);
		C->SetPeriodic(); // 也可在pnts追加起点，曲线会更加光滑。
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(aEdge);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		BRepAdaptor_Surface surface(aFace);
		gp_Dir direc = surface.Plane().Axis().Direction();
		//gp_Dir direc(0 , 0 , 1);
		gp_Vec v = direc;
		v *= 100;
		TopoDS_Shape P1 = BRepPrimAPI_MakePrism(aFace , v);
		//TopoDS_Shape P1 = BRepPrimAPI_MakePrism(aFace , direc);
		//TopoDS_Shape P1 = BRepPrimAPI_MakePrism(aFace , direc,false);

		Handle(AIS_InteractiveObject) aisPrism = new MAisDemo(P1);
		myContext->Display(aisPrism , 1 , 0 , false);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Boolean Operations")
	{
		TopoDS_Shape box = BRepPrimAPI_MakeBox(10 , 20 , 30);
		Handle(AIS_InteractiveObject) aisBox = new MAisDemo(box);
		myContext->Display(aisBox , 1 , 0 , false);

		TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(gp_Pnt(10 , 5 , 0) , 5);
		Handle(AIS_InteractiveObject) aissphere = new MAisDemo(sphere);
		myContext->Display(aissphere , 1 , 0 , false);

		TopoDS_Shape aFuse = BRepAlgoAPI_Fuse(box , sphere);
		TopAbs::Print(aFuse.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) aisFuse = new MAisDemo(aFuse);
		myContext->Display(aisFuse , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(50 , 0 , 0));
		aisFuse->SetLocalTransformation(T);

		TopoDS_Shape aCut = BRepAlgoAPI_Cut(box , sphere);
		TopAbs::Print(aCut.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) aisCut = new MAisDemo(aCut);
		myContext->Display(aisCut , 1 , 0 , false);
		T.SetTranslation(gp_Vec(100 , 0 , 0));
		aisCut->SetLocalTransformation(T);

		TopoDS_Shape aCommon = BRepAlgoAPI_Common(box , sphere);
		TopAbs::Print(aCommon.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) aisCommon = new MAisDemo(aCommon);
		myContext->Display(aisCommon , 1 , 0 , false);
		T.SetTranslation(gp_Vec(150 , 0 , 0));
		aisCommon->SetLocalTransformation(T);

		// 相交的截面（由edge组成）
		TopoDS_Shape aSection = BRepAlgoAPI_Section(box , sphere);
		TopAbs::Print(aSection.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) aisSection = new MAisDemo(aSection);
		myContext->Display(aisSection , 1 , 0 , false);
		T.SetTranslation(gp_Vec(200 , 0 , 0));
		aisSection->SetLocalTransformation(T);

		Handle(Geom_Plane) geomPln = new Geom_Plane(gp_Pnt(0 , 0 , 20) , gp_Dir(0 , 0 , 1));
		BRepBuilderAPI_MakeShell aShell = BRepBuilderAPI_MakeShell(geomPln , -15 , 15 , -25 , 25);
		Handle(AIS_InteractiveObject) aisShell = new MAisDemo(aShell);
		myContext->Display(aisShell , 1 , 0 , false);

		// 只能shell为object,solid为tool
		TopoDS_Shape aCutShell = BRepAlgoAPI_Cut(aShell , box);
		TopAbs::Print(aCutShell.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) aisCutShell = new MAisDemo(aCutShell);
		myContext->Display(aisCutShell , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 100 , 0));
		aisCutShell->SetLocalTransformation(T);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Getting normal for the face")
	{
		Handle(Geom_Plane) geomPln = new Geom_Plane(gp_Pnt(0,0,0), gp::DZ());
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(geomPln , -100 , 100 , -50 , 50 , 0);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);
		gp_Trsf T;
		T.SetRotation(gp::OY(), M_PI / 4);
		aisFace->SetLocalTransformation(T);

		Handle(Geom_Surface) sur = BRep_Tool::Surface(aFace);
		gp_Trsf T1 = aisFace->Transformation();
		sur->Transform(T1);

		gp_Dir dir;
		gp_Pnt pnt;
		sur->D0(0 , 0, pnt);
		BOPTools_AlgoTools3D::GetNormalToSurface(sur , 0 , 0 , dir);
		Handle(AIS_Axis) axis = new AIS_Axis(gp_Ax1(pnt ,dir), 100);
		axis->SetColor(Quantity_NOC_YELLOW);
		myContext->Display(axis , 1 , 0 , false);

		BRepAdaptor_Surface surface(aFace);
		gp_Dir dir1 = surface.Plane().Axis().Direction();
		gp_Pnt pnt1;
		sur->D0(50 , 20 , pnt1);
		Handle(AIS_Axis) axis1 = new AIS_Axis(gp_Ax1(pnt1 , dir1) , 100);
		axis1->SetColor(Quantity_NOC_PURPLE);
		myContext->Display(axis1 , 1 , 0 , false);
	}
	else if (cbb_BRepPrimAPI->currentText() == "History support")
	{
		TopoDS_Shape aS = BRepPrimAPI_MakeBox(10 , 20 , 30);
		Handle(AIS_InteractiveObject) aisS = new MAisDemo(aS);
		myContext->Display(aisS , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 0 , 100));
		BRepBuilderAPI_Transform trsf(aS , T);

		//TopTools_ListOfShape anArguments;
		//anArguments.Append(aS);
		//BRepTools_History aHistory(anArguments , trsf);

		BRepTools_History aHistory;
		aHistory.AddModified(aS , trsf);

		TopoDS_Shape res = aHistory.Modified(aS).Last();
		T.SetTranslation(gp_Vec(50 , 50 , 0));
		BRepBuilderAPI_Transform trsf1(res , T);
		aHistory.AddModified(aS , trsf1);

		TopoDS_Shape res1 = aHistory.Modified(aS).Last();
		T.SetTranslation(gp_Vec(0 , 0 , 50));
		BRepBuilderAPI_Transform trsf2(res1 , T);
		aHistory.AddModified(aS , trsf2);

		TopTools_ListOfShape aMo = aHistory.Modified(aS);
		std::cout << aMo.Size() << std::endl;
		for (auto it = aMo.begin(); it != aMo.end(); ++it)
		{
			Handle(AIS_InteractiveObject) ais = new MAisDemo(*it);
			myContext->Display(ais , 1 , 0 , false);
		}
		aHistory.Dump(std::cout);
		std::cout << std::endl;

		gp_Pnt pnt(100 , 100 , 0);
		pnt.DumpJson(std::cout);
		std::cout << std::endl;

		aS.DumpJson(std::cout);
	}
	else if (cbb_BRepPrimAPI->currentText() == "Fillets and Chamfers")
	{
		TopoDS_Solid Box = BRepPrimAPI_MakeBox(100 , 200 , 300);
		BRepFilletAPI_MakeFillet  MFFillet(Box);
		TopExp_Explorer  ex(Box , TopAbs_EDGE);
		double r = 10.;
		int i = 0;
		// 一个MFFillet实例中选相邻边正常倒角，
		// 若先倒角一条边，再新创建了个MFFillet实例，倒相邻边，那么会给与两相邻边都相邻的第三条边也倒角
		while (ex.More())
		{
			if (i == 0 || i == 1)
			{
				MFFillet.Add(r , TopoDS::Edge(ex.Current()));
			}
			i++;
			ex.Next();
		}
		Handle(AIS_InteractiveObject) aisFillet = new MAisDemo(MFFillet.Shape());
		myContext->Display(aisFillet , 1 , 0 , false);

		TopoDS_Solid BoxChamfer = BRepPrimAPI_MakeBox(gp_Pnt(200 , 0 , 0) , 100 , 200 , 300);
		BRepFilletAPI_MakeChamfer  MFChamfer(BoxChamfer);
		TopExp_Explorer  exChamfer(BoxChamfer , TopAbs_EDGE);
		double rChamfer = 10.;
		while (exChamfer.More())
		{
			MFChamfer.Add(rChamfer , TopoDS::Edge(exChamfer.Current()));
			exChamfer.Next();
		}
		Handle(AIS_InteractiveObject) aisChamfer = new MAisDemo(MFChamfer.Shape());
		myContext->Display(aisChamfer , 1 , 0 , false);

		TopoDS_Solid BoxFillet2d = BRepPrimAPI_MakeBox(gp_Pnt(400 , 0 , 0) , 100 , 200 , 300);
		TopExp_Explorer  ex1(BoxFillet2d , TopAbs_FACE);

		TopoDS_Face F = TopoDS::Face(ex1.Current());
		BRepFilletAPI_MakeFillet2d  MFFillet2d(F);
		double rFillet2d = 20;
		TopTools_IndexedMapOfShape mapVertex;
		// 教程错误，以下为修正后代码
		TopExp::MapShapes(F , TopAbs_VERTEX , mapVertex);
		for (int i = 1; i <= mapVertex.Size(); ++i)
		{
			MFFillet2d.AddFillet(TopoDS::Vertex(mapVertex(i)) , rFillet2d);
		}

		Handle(AIS_InteractiveObject) aisFillet2d = new MAisDemo(MFFillet2d.Shape());
		myContext->Display(aisFillet2d , 1 , 0 , false);
	}

	view_occt->fitAll();
}

void MainWindow::runBRepOffsetAPI()
{
	if (cbb_BRepOffsetAPI->currentText() == "MakePipe")
	{
		Handle(Geom_Circle) C = new Geom_Circle(gp_Ax2(gp_Pnt(500 , 0 , 0) , gp::DY()) , 100);
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(C);
		TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(aEdge);
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire);
		Handle(AIS_InteractiveObject) aisWire = new MAisDemo(aWire);
		myContext->Display(aisWire , 1 , 0 , false);
		Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
		myContext->Display(aisFace , 1 , 0 , false);

		std::vector<gp_Pnt> pntsPath = { gp_Pnt(0,100,100), gp_Pnt(0,200,300), gp_Pnt(0,400,300), gp_Pnt(0,500,500) };
		Handle(Geom_BSplineCurve) CPath = createBSplineCurve(pntsPath);
		TopoDS_Edge aEdgePath = BRepBuilderAPI_MakeEdge(CPath);
		TopoDS_Wire aWirePath = BRepBuilderAPI_MakeWire(aEdgePath);
		Handle(AIS_InteractiveObject) aisWirePath = new MAisDemo(aWirePath);
		myContext->Display(aisWirePath , 1 , 0 , false);

		int startParam = CPath->FirstParameter();
		TopoDS_Shape aProfileNew = correctionProfile(aFace , gp_Pnt(500 , 0 , 0) , CPath , startParam);

		// 需将profile的中心点旋转/移动到path起点处
		TopoDS_Shape P = BRepOffsetAPI_MakePipe(aWirePath , aProfileNew);
		TopAbs::Print(P.ShapeType() , std::cout);
		Handle(AIS_InteractiveObject) aisPipe = new MAisDemo(P);
		myContext->Display(aisPipe , 1 , 0 , false);
	}
	else if (cbb_BRepOffsetAPI->currentText() == "Offset computation")
	{
		gp_Pln aPln = gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		TopoDS_Shape aShape = BRepBuilderAPI_MakeFace(aPln , 0 , 10 , 0 , 10);
		//TopoDS_Shape aShape = BRepPrimAPI_MakeBox(10 , 20 , 30);
		Handle(AIS_InteractiveObject) aisShape = new MAisDemo(aShape);
		myContext->Display(aisShape , 1 , 0 , false);

		BRepOffsetAPI_MakeOffsetShape OffsetMaker1;
		double OffsetValue = 5.;
		OffsetMaker1.PerformByJoin(aShape , OffsetValue , Precision::Confusion());
		//OffsetMaker1.PerformBySimple(aShape , OffsetValue);
		TopoDS_Shape NewShape;
		if (OffsetMaker1.IsDone())
			NewShape = OffsetMaker1.Shape();
		Handle(AIS_InteractiveObject) aisOffset = new MAisDemo(NewShape);
		myContext->Display(aisOffset , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(50 , 0 , 0));
		aisOffset->SetLocalTransformation(T);
	}
	else if (cbb_BRepOffsetAPI->currentText() == "Shelling")
	{
		TopoDS_Shape SolidInitial = BRepPrimAPI_MakeBox(10 , 20 , 30);
		Handle(AIS_InteractiveObject) aisInitial = new MAisDemo(SolidInitial , true);
		myContext->Display(aisInitial , 1 , 0 , false);

		TopTools_ListOfShape LCF;
		TopExp_Explorer ex(SolidInitial , TopAbs_FACE);
		int i = 1;
		while (ex.More())
		{
			if (i == 2 || i == 6)
				//if (i == 6)
			{
				LCF.Append(ex.Current());
			}

			ex.Next();
			++i;
		}

		BRepOffsetAPI_MakeThickSolid SolidMaker;
		double Of = 2.;
		SolidMaker.MakeThickSolidByJoin(SolidInitial , LCF , Of , Precision::Confusion());
		TopoDS_Shape Result;
		if (SolidMaker.IsDone())
			Result = SolidMaker.Shape();
		Handle(AIS_InteractiveObject) aisOffset = new MAisDemo(Result);
		myContext->Display(aisOffset , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(50 , 0 , 0));
		aisOffset->SetLocalTransformation(T);

		double Of1 = -2.;
		SolidMaker.MakeThickSolidByJoin(SolidInitial , LCF , Of1 , Precision::Confusion());
		Handle(AIS_InteractiveObject) aisOffset1 = new MAisDemo(SolidMaker.Shape());
		myContext->Display(aisOffset1 , 1 , 0 , false);
		T.SetTranslation(gp_Vec(100 , 0 , 0));
		aisOffset1->SetLocalTransformation(T);
	}
	else if (cbb_BRepOffsetAPI->currentText() == "loft")
	{
		Handle(Geom_Circle) c = new Geom_Circle(gp_Ax2(gp_Pnt(0 , 0 , 0) , gp_Dir(1 , 0 , 0)) , 10);
		TopoDS_Edge e = BRepBuilderAPI_MakeEdge(c);
		BRepBuilderAPI_MakeWire w;
		w.Add(e);
		TopoDS_Wire aProfile = w.Wire();

		Handle(Geom_Circle) c1 = new Geom_Circle(gp_Ax2(gp_Pnt(100 , 100 , 0) , gp_Dir(1 , 0 , 0)) , 20);
		TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(c1);
		BRepBuilderAPI_MakeWire w1;
		w1.Add(e1);
		TopoDS_Wire aProfile1 = w1.Wire();

		Handle(Geom_Circle) c2 = new Geom_Circle(gp_Ax2(gp_Pnt(300 , 500 , 0) , gp_Dir(-1 , 1 , 0)) , 40);
		TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(c2);
		BRepBuilderAPI_MakeWire w2;
		w2.Add(e2);
		TopoDS_Wire aProfile2 = w2.Wire();

		TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(gp_Pnt(300 , 500 , 0) , gp_Pnt(400 , 600 , -200));
		TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(gp_Pnt(400 , 600 , -200) , gp_Pnt(400 , 600 , 200));
		TopoDS_Edge e5 = BRepBuilderAPI_MakeEdge(gp_Pnt(400 , 600 , 200) , gp_Pnt(300 , 500 , 0));
		BRepBuilderAPI_MakeWire w3;
		w3.Add(e3);
		w3.Add(e4);
		w3.Add(e5);
		TopoDS_Wire aProfile3 = w3.Wire();

		// profile中心点在曲线时，需调整法线方向，否则生成异常。没有pipeShell好用
		// 支持不同形状profile
		BRepOffsetAPI_ThruSections loft(true , false);
		loft.AddWire(aProfile);
		loft.AddWire(aProfile1);
		loft.AddWire(aProfile3);

		TopoDS_Shape aShape = loft.Shape();
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		myContext->Display(ais , 1 , 0 , false);
	}
	else if (cbb_BRepOffsetAPI->currentText() == "PipeShell")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0,0,0), gp_Pnt(50,20,0), gp_Pnt(80,60,0) };
		BRepBuilderAPI_MakePolygon MP;
		for (auto p : pnts)
		{
			MP.Add(p);
		}
		TopoDS_Wire path = MP.Wire();
		Handle(AIS_InteractiveObject) aisPath = new MAisDemo(path);
		myContext->Display(aisPath , 1 , 0 , false);

		Handle(Geom_Circle) cir = new Geom_Circle(gp_Ax2(gp_Pnt(0 , 0 , 0) , gp_Dir(1 , 0 , 0)) , 5);
		TopoDS_Shape aProfile = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(cir));
		Handle(AIS_InteractiveObject) aisProfile = new MAisDemo(aProfile);
		myContext->Display(aisProfile , 1 , 0 , false);

		BRepOffsetAPI_MakePipeShell PipeShell(TopoDS::Wire(path));

		// WithContact将profile移动到path上，WithCorrection自动调整法向量与path相符（相比手动调整位置来说不太好用,建议手动调整）
		// 添加多个profile时，需将所有profile中心点放在path上,e.g. profile1放在第二个构造点，后续自动生成渐变的profile
		// 支持不同形状profile
		PipeShell.Add(aProfile , false , true);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(PipeShell.Shape());
		myContext->Display(ais , 1 , 0 , false);

		PipeShell.SetTransitionMode(BRepBuilderAPI_RightCorner);
		PipeShell.Build();
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(PipeShell.Shape());
		myContext->Display(ais1 , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 0 , 20));
		ais1->SetLocalTransformation(T);

		PipeShell.SetTransitionMode(BRepBuilderAPI_RoundCorner);
		PipeShell.Build();
		Handle(AIS_InteractiveObject) ais2 = new MAisDemo(PipeShell.Shape());
		myContext->Display(ais2 , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 0 , 40));
		ais2->SetLocalTransformation(T);

		Handle(Geom_Circle) cir1 = new Geom_Circle(
	gp_Ax2(gp_Pnt(80 , 60 , 0) , gp_Vec(gp_Pnt(50 , 20 , 0) , gp_Pnt(80 , 60 , 0))) ,
	10);
		TopoDS_Shape aProfile1 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(cir1));
		Handle(AIS_InteractiveObject) aisProfile1 = new MAisDemo(aProfile1);
		myContext->Display(aisProfile1 , 1 , 0 , false);

		// 添加多个profile时,sharpPath的过渡生成不理想,自动过渡比较耗时
		PipeShell.SetTransitionMode(BRepBuilderAPI_Transformed);
		//PipeShell.SetTransitionMode(BRepBuilderAPI_RightCorner);
		PipeShell.Add(aProfile1);
		PipeShell.Build();
		Handle(AIS_InteractiveObject) ais3 = new MAisDemo(PipeShell.Shape());
		myContext->Display(ais3 , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 0 , 60));
		ais3->SetLocalTransformation(T);

		// 曲线路径
		std::vector<gp_Pnt> pnts1 = { gp_Pnt(200,0,0), gp_Pnt(220,210,0), gp_Pnt(210,220,0), gp_Pnt(200,230,0) };
		Handle(Geom_BSplineCurve) C = createBSplineCurve(pnts1);
		TopoDS_Wire path1 = BRepBuilderAPI_MakeWire(BRepBuilderAPI_MakeEdge(C));
		Handle(AIS_InteractiveObject) aisPath1 = new MAisDemo(path1);
		myContext->Display(aisPath1 , 1 , 0 , false);

		TopoDS_Shape wCorrection = correctionProfile(aProfile , gp_Pnt(0 , 0 , 0) , C , C->FirstParameter());
		Handle(AIS_InteractiveObject) aisCorrection = new MAisDemo(wCorrection);
		myContext->Display(aisCorrection , 1 , 0 , false);

		TopoDS_Shape wCorrection1 = correctionProfile(aProfile1 , gp_Pnt(80 , 60 , 0) , C , C->LastParameter());
		Handle(AIS_InteractiveObject) aisCorrection1 = new MAisDemo(wCorrection1);
		myContext->Display(aisCorrection1 , 1 , 0 , false);

		BRepOffsetAPI_MakePipeShell PipeShell1(TopoDS::Wire(path1));
		PipeShell1.Add(wCorrection , false , false);
		PipeShell1.Add(wCorrection1 , false , false);
		Handle(AIS_InteractiveObject) ais4 = new MAisDemo(PipeShell1.Shape());
		myContext->Display(ais4 , 1 , 0 , false);

		std::vector<gp_Pnt> pnts2 = { gp_Pnt(-20,10,0), gp_Pnt(20,10,0), gp_Pnt(20,-10,0) ,gp_Pnt(-20,-10,0) };
		BRepBuilderAPI_MakePolygon MPRect;
		for (auto p : pnts2)
		{
			MPRect.Add(p);
		}
		MPRect.Close();
		TopoDS_Shape aProfile2 = MPRect.Wire();

		TopoDS_Shape wCorrection2 = correctionProfile(aProfile2 , gp_Pnt(0 , 0 , 0) , C , C->LastParameter());
		Handle(AIS_InteractiveObject) aisCorrection2 = new MAisDemo(wCorrection2);
		myContext->Display(aisCorrection2 , 1 , 0 , false);

		BRepOffsetAPI_MakePipeShell PipeShell2(TopoDS::Wire(path1));
		PipeShell2.Add(wCorrection , false , false);
		PipeShell2.Add(wCorrection2 , false , false);
		Handle(AIS_InteractiveObject) ais5 = new MAisDemo(PipeShell2.Shape());
		myContext->Display(ais5 , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 0 , 50));
		ais5->SetLocalTransformation(T);

		// path不封闭时，生成的是两端开放的shell，需手动封口
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(TopoDS::Wire(wCorrection));
		TopoDS_Shell shell;
		BRep_Builder builder;
		builder.MakeShell(shell);
		builder.Add(shell , aFace);

		TopoDS_Face aFace1 = BRepBuilderAPI_MakeFace(TopoDS::Wire(wCorrection2));
		builder.Add(shell , aFace1);

		BRepBuilderAPI_MakeSolid solidBuilder;
		solidBuilder.Add(shell);
		solidBuilder.Add(TopoDS::Shell(PipeShell2.Shape()));
		TopoDS_Shape aShape = solidBuilder.Solid();
		TopAbs::Print(aShape.ShapeType() , std::cout);

		//BRepBuilderAPI_Sewing Sew;
		//Sew.Add(shell);
		//Sew.Add(TopoDS::Shell(PipeShell2.Shape()));
		//Sew.Perform();
		//TopoDS_Shape aShape = Sew.SewedShape();
		//TopAbs::Print(aShape.ShapeType() , std::cout);

		Handle(AIS_InteractiveObject) aisSolid = new MAisDemo(aShape);
		myContext->Display(aisSolid , 1 , 0 , false);
		T.SetTranslation(gp_Vec(0 , 0 , 100));
		aisSolid->SetLocalTransformation(T);
	}

	view_occt->fitAll();
}

void MainWindow::runModification()
{
	if (cbb_Modification->currentText() == "Transformation")
	{
		TopoDS_Shape aBox = BRepPrimAPI_MakeBox(100 , 200 , 300);

		Handle(AIS_InteractiveObject) aisBox = new MAisDemo(aBox);
		myContext->Display(aisBox , 1 , 0 , false);

		gp_Trsf T;
		T.SetTranslation(gp_Vec(300 , 0 , 0));
		BRepBuilderAPI_Transform trsf(aBox , T);
		Handle(AIS_InteractiveObject) aisTrsf = new MAisDemo(trsf.Shape());
		myContext->Display(aisTrsf , 1 , 0 , false);

		gp_Quaternion quater(gp_Vec(0 , 1 , 0) , gp_Vec(1 , 1 , 0));
		T.SetRotation(quater);
		BRepBuilderAPI_Transform trsf1(trsf.Shape() , T);
		Handle(AIS_InteractiveObject) aisTrsf1 = new MAisDemo(trsf1.Shape());
		myContext->Display(aisTrsf1 , 1 , 0 , false);

		T.SetTransformation(quater , gp_Vec(600 , 0 , 0));
		BRepBuilderAPI_Transform trsf2(aBox , T);
		Handle(AIS_InteractiveObject) aisTrsf2 = new MAisDemo(trsf2.Shape());
		myContext->Display(aisTrsf2 , 1 , 0 , false);
	}
	else if (cbb_Modification->currentText() == "Duplication")
	{
		Handle(Geom_Plane) geomPln = new Geom_Plane(gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1)));

		TopoDS_Shape aFace = BRepBuilderAPI_MakeFace(geomPln , -100 , 100 , -100 , 100 , 0);
		Handle(AIS_InteractiveObject) aisO = new MAisDemo(aFace);
		myContext->Display(aisO , 1 , 0 , false);

		TopoDS_Shape myCopy = BRepBuilderAPI_Copy(aFace);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(myCopy);
		myContext->Display(ais , 1 , 0 , false);
	}
	else if (cbb_Modification->currentText() == "Sewing")
	{
		// 类似fuse功能，sewing可调整间隙，也可参考PipeShell示例
		Handle(Geom_Plane) geomPln1 = new Geom_Plane(gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1)));
		Handle(Geom_Plane) geomPln2 = new Geom_Plane(gp_Pln(gp_Pnt(100 , 0 , 100) , gp_Dir(1 , 0 , 0)));
		Handle(Geom_Plane) geomPln3 = new Geom_Plane(gp_Pln(gp_Pnt(-100 , 0 , 100) , gp_Dir(1 , 0 , 0)));
		std::vector<Handle(Geom_Plane)> geomPlns = { geomPln1 ,geomPln2 ,geomPln3 };
		std::vector<TopoDS_Face> faces;
		for (auto e : geomPlns)
		{
			TopoDS_Face aFace = BRepBuilderAPI_MakeFace(e , -100 , 100 , -100 , 100 , 0);
			faces.push_back(aFace);

			Handle(AIS_InteractiveObject) aisFace = new MAisDemo(aFace);
			myContext->Display(aisFace , 1 , 0 , false);
		}

		BRepBuilderAPI_Sewing Sew;
		for (auto e : faces)
		{
			Sew.Add(e);
		}
		Sew.Perform();
		TopoDS_Shape aShape = Sew.SewedShape();
		TopAbs::Print(aShape.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		myContext->Display(ais , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(300 , 0 , 0));
		ais->SetLocalTransformation(T);

		//TopoDS_Compound aComp;
		//BRep_Builder aB;
		//aB.MakeCompound(aComp);
		//aB.Add(aComp , faces[0]);
		//aB.Add(aComp , faces[1]);
		//aB.Add(aComp , faces[2]);

		//BRepBuilderAPI_Sewing Sew;
		//Sew.Load(aComp);
		//Sew.Add(faces[0]);
		//Sew.Add(faces[1]);
		//Sew.Add(faces[2]);
		//Sew.Perform();
		//TopoDS_Shape aShape = Sew.SewedShape();
		//TopAbs::Print(aShape.ShapeType() , std::cout);
		//std::cout << std::endl;
		//Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		//myContext->Display(ais , 1 , 0 , false);
		//gp_Trsf T;
		//T.SetTranslation(gp_Vec(300 , 0 , 0));
		//ais->SetLocalTransformation(T);
	}
	else if (cbb_Modification->currentText() == "BRepFeat_MakePrism")
	{
		TopoDS_Shape Sbase = BRepPrimAPI_MakeBox(400. , 250. , 300.);
		Handle(AIS_InteractiveObject) aisSbase = new MAisDemo(Sbase , true);
		myContext->Display(aisSbase , 1 , 0 , false);

		TopExp_Explorer Ex(Sbase , TopAbs_FACE);
		Ex.Next();
		Ex.Next();
		Ex.Next();
		Ex.Next();
		Ex.Next();
		TopoDS_Face F = TopoDS::Face(Ex.Current());

		Handle(Geom_Surface) surf = BRep_Tool::Surface(F);
		gp_Circ2d c(gp_Ax2d(gp_Pnt2d(200. , 130.) , gp_Dir2d(1. , 0.)) , 50.);
		Handle(Geom2d_Curve) aline = new Geom2d_Circle(c);

		BRepBuilderAPI_MakeWire MW;
		MW.Add(BRepBuilderAPI_MakeEdge(aline , surf));
		TopoDS_Face Fbase = BRepBuilderAPI_MakeFace(MW.Wire());

		Handle(AIS_InteractiveObject) aisFbase = new MAisDemo(Fbase);
		myContext->Display(aisFbase , 1 , 0 , false);

		BRepLib::BuildCurves3d(Fbase); // 没有此步骤后面无法扫掠
		gp_Dir Extrusion(0. , 0. , 1.);
		// TopoDS_Face()指定F也行
		BRepFeat_MakePrism thePrism(Sbase , Fbase , F , Extrusion , true , true);
		thePrism.Perform(100.);

		TopoDS_Shape res = thePrism.Shape();
		TopAbs::Print(res.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) ais = new MAisDemo(res);
		myContext->Display(ais , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(500 , 0 , 0));
		ais->SetLocalTransformation(T);
	}
	else if (cbb_Modification->currentText() == "BRepFeat_MakePipe")
	{
		TopoDS_Shape S = BRepPrimAPI_MakeBox(400. , 250. , 300.);
		Handle(AIS_InteractiveObject) aisSbase = new MAisDemo(S , true);
		myContext->Display(aisSbase , 1 , 0 , false);

		TopExp_Explorer Ex;
		Ex.Init(S , TopAbs_FACE);
		Ex.Next();
		Ex.Next();
		TopoDS_Face F1 = TopoDS::Face(Ex.Current());

		Handle(Geom_Surface) surf = BRep_Tool::Surface(F1);
		BRepBuilderAPI_MakeWire MW1;
		gp_Pnt2d p1 , p2;
		p1 = gp_Pnt2d(100. , 100.);
		p2 = gp_Pnt2d(200. , 100.);
		Handle(Geom2d_Line) aline = GCE2d_MakeLine(p1 , p2).Value();
		MW1.Add(BRepBuilderAPI_MakeEdge(aline , surf , 0. , p1.Distance(p2)));

		p1 = p2;
		p2 = gp_Pnt2d(150. , 200.);
		aline = GCE2d_MakeLine(p1 , p2).Value();
		MW1.Add(BRepBuilderAPI_MakeEdge(aline , surf , 0. , p1.Distance(p2)));

		p1 = p2;
		p2 = gp_Pnt2d(100. , 100.);
		aline = GCE2d_MakeLine(p1 , p2).Value();
		MW1.Add(BRepBuilderAPI_MakeEdge(aline , surf , 0. , p1.Distance(p2)));

		TopoDS_Face FP = BRepBuilderAPI_MakeFace(surf , MW1.Wire() , false);
		BRepLib::BuildCurves3d(FP);

		TColgp_Array1OfPnt CurvePoles(1 , 3);
		gp_Pnt pt = gp_Pnt(150. , 0. , 150.);
		CurvePoles(1) = pt;
		pt = gp_Pnt(200. , 100. , 150.);
		CurvePoles(2) = pt;
		pt = gp_Pnt(150. , 200. , 150.);
		CurvePoles(3) = pt;
		Handle(Geom_BezierCurve) curve = new Geom_BezierCurve(CurvePoles);
		TopoDS_Edge E = BRepBuilderAPI_MakeEdge(curve);
		TopoDS_Wire W = BRepBuilderAPI_MakeWire(E);

		BRepFeat_MakePipe MKPipe(S , FP , F1 , W , false , true);
		MKPipe.Perform();
		TopoDS_Shape res = MKPipe.Shape();
		TopAbs::Print(res.ShapeType() , std::cout);
		std::cout << std::endl;
		Handle(AIS_InteractiveObject) ais = new MAisDemo(res);
		myContext->Display(ais , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(500 , 0 , 0));
		ais->SetLocalTransformation(T);
	}
	else if (cbb_Modification->currentText() == "3DModelDefeaturing")
	{
		TopoDS_Shape S = BRepPrimAPI_MakeBox(200. , 600. , 100.);
		TopoDS_Shape S1 = BRepPrimAPI_MakeBox(gp_Pnt(100 , -300 , 50.) , 200. , 600. , 100.);
		TopoDS_Shape S2 = BRepPrimAPI_MakeBox(gp_Pnt(50 , 300 , 0) , 200. , 100. , 100.);
		TopoDS_Shape aCut = BRepAlgoAPI_Cut(S , S1);
		aCut = BRepAlgoAPI_Cut(aCut , S2);
		Handle(AIS_InteractiveObject) aisCut = new MAisDemo(aCut, true);
		myContext->Display(aisCut , 1 , 0 , false);

		TopExp_Explorer ex(aCut , TopAbs_FACE);
		int i = 1;
		TopTools_ListOfShape aFeatures;
		TopTools_ListOfShape aFeatures1;
		while (ex.More())
		{
			TopoDS_Face face = TopoDS::Face(ex.Current());
			if (i == 11 || i == 12)
				aFeatures1.Append(face);
			if (i == 10 || i == 11)
				aFeatures.Append(face);
			++i;
			ex.Next();
		}
		BRepAlgoAPI_Defeaturing aDF;
		aDF.SetShape(aCut);
		aDF.AddFacesToRemove(aFeatures);
		aDF.SetRunParallel(false);
		aDF.SetToFillHistory(true);
		aDF.Build();
		TopoDS_Shape aResult = aDF.Shape();
		Handle(AIS_InteractiveObject) aisResult = new MAisDemo(aResult);
		myContext->Display(aisResult , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(300 , 0 , 0));
		aisResult->SetLocalTransformation(T);

		BRepAlgoAPI_Defeaturing aDF1;
		aDF1.SetShape(aCut);
		aDF1.AddFacesToRemove(aFeatures1);
		aDF1.SetRunParallel(false);
		aDF1.SetToFillHistory(true);
		aDF1.Build();
		TopoDS_Shape aResult1 = aDF1.Shape();
		Handle(AIS_InteractiveObject) aisResult1 = new MAisDemo(aResult1);
		myContext->Display(aisResult1 , 1 , 0 , false);
		T.SetTranslation(gp_Vec(700 , 0 , 0));
		aisResult1->SetLocalTransformation(T);
	}
	else if (cbb_Modification->currentText() == "3DModelPeriodicity")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0,0,0), gp_Pnt(0,0,10) ,gp_Pnt(5,0,10),gp_Pnt(5,0,5) ,gp_Pnt(10,0,5) ,
			gp_Pnt(10,0,0),gp_Pnt(0,0,0) };
		BRepBuilderAPI_MakePolygon MP;
		for (auto p : pnts)
		{
			MP.Add(p);
		}
		TopoDS_Wire aWire = MP.Wire();
		TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aWire);
		TopoDS_Shape aShape = BRepPrimAPI_MakePrism(aFace , gp_Vec(0 , 5 , 0));
		//Handle(AIS_InteractiveObject) ais = new MAisDemo(aShape);
		//myContext->Display(ais , 1 , 0 , false);

		BOPAlgo_MakePeriodic aPeriodicityMaker;
		aPeriodicityMaker.SetShape(aShape);
		aPeriodicityMaker.MakeXPeriodic(true , 11);
		aPeriodicityMaker.MakeZPeriodic(true , 11);
		//aPeriodicityMaker.SetTrimmed(0 , false);
		//aPeriodicityMaker.SetRunParallel(true);
		aPeriodicityMaker.Perform();
		//TopoDS_Shape aPeriodicShape = aPeriodicityMaker.Shape();
		aPeriodicityMaker.XRepeat(1);
		aPeriodicityMaker.ZRepeat(1);
		TopoDS_Shape aRepeat = aPeriodicityMaker.RepeatedShape();
		aPeriodicityMaker.ClearRepetitions();

		Handle(AIS_InteractiveObject) aisRepeat = new MAisDemo(aRepeat);
		myContext->Display(aisRepeat , 1 , 0 , false);
	}
	else if (cbb_Modification->currentText() == "drillExample")
	{
		TopoDS_Shape plate = BRepPrimAPI_MakeBox(gp_Pnt(-50 , -50 , 0) , 100 , 100 , 1);
		TopoDS_Shape drill = BRepPrimAPI_MakeCylinder(gp_Ax2(gp_Pnt(-48 , -48 , 0) , gp_Dir(0 , 0 , 1)) , 1 , 1);

		BOPAlgo_MakePeriodic aPeriodicityMaker;
		aPeriodicityMaker.SetShape(drill);
		aPeriodicityMaker.MakeXPeriodic(true , 4);
		aPeriodicityMaker.MakeYPeriodic(true , 4);
		aPeriodicityMaker.Perform();
		//aPeriodicityMaker.SetTrimmed(0 , true, 50);
		//aPeriodicityMaker.SetTrimmed(1 , true , 50);
		aPeriodicityMaker.XRepeat(24);
		aPeriodicityMaker.YRepeat(24);
		BRepAlgoAPI_Cut B(plate , aPeriodicityMaker.RepeatedShape());
		B.SetRunParallel(true);
		TopoDS_Shape aCut = B.Shape();
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aCut);
		myContext->Display(ais , 1 , 0 , false);
	}

	view_occt->fitAll();
}

void MainWindow::runBoolean()
{
	if (cbb_Boolean->currentText() == "GFA")
	{
		BOPAlgo_Builder aBuilder;
		// Setting arguments
		TopoDS_Shape aShape = BRepPrimAPI_MakeBox(100 , 100 , 200);
		TopoDS_Shape aShape1 = BRepPrimAPI_MakeBox(gp_Pnt(50 , 50 , 100) , 100 , 100 , 50);
		TopoDS_Shape aShape2 = BRepPrimAPI_MakeSphere(30);
		std::vector< TopoDS_Shape> shapes = { { aShape ,aShape1 ,aShape2 } };
		TopTools_ListOfShape aLSObjects;
		for (auto& s : shapes)
		{
			aLSObjects.Append(s);
		}
		aBuilder.SetArguments(aLSObjects);

		// Setting options for GF
		// Set parallel processing mode (default is false)
		aBuilder.SetRunParallel(true);

		// Set Fuzzy value (default is Precision::Confusion())
		double aFuzzyValue = 1.e-5;
		aBuilder.SetFuzzyValue(aFuzzyValue);

		// Set safe processing mode (default is false)
		aBuilder.SetNonDestructive(true);

		// Set Gluing mode for coinciding arguments (default is off)
		aBuilder.SetGlue(BOPAlgo_GlueShift);

		// Disabling/Enabling the check for inverted solids (default is true)
		aBuilder.SetCheckInverted(false);

		// Set OBB usage (default is false)
		aBuilder.SetUseOBB(true);

		// Perform the operation
		aBuilder.Perform();

		TopoDS_Shape aResult = aBuilder.Shape();
		TopAbs::Print(aResult.ShapeType() , std::cout);
		std::cout << std::endl;

		Handle(AIS_InteractiveObject) aisGFA = new MAisDemo(aResult);
		myContext->Display(aisGFA , 1 , 0 , false);
	}
	else if (cbb_Boolean->currentText() == "SPA")
	{
		BOPAlgo_Splitter aBuilder;
		// Setting arguments
		TopoDS_Shape aShape = BRepPrimAPI_MakeSphere(50);
		std::vector< TopoDS_Shape> shapes = { { aShape } };
		TopTools_ListOfShape aLSObjects;
		for (auto& s : shapes)
		{
			aLSObjects.Append(s);
		}
		aBuilder.SetArguments(aLSObjects);

		TopoDS_Shape aFace = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , -10) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		TopoDS_Shape aFace1 = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , 10) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		TopoDS_Shape aFace2 = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , 40) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		std::vector< TopoDS_Shape> tools = { { aFace,aFace1,aFace2 } };
		TopTools_ListOfShape aLSTools;
		for (auto& s : tools)
		{
			aLSTools.Append(s);
			Handle(AIS_InteractiveObject) aisF = new MAisDemo(s);
			aisF->SetTransparency(0.8);
			aisF->Attributes()->ShadingAspect()->SetColor(Quantity_NOC_BLUE);
			myContext->Display(aisF , 1 , 0 , false);
		}
		aBuilder.SetTools(aLSTools);

		aBuilder.SetRunParallel(true);
		aBuilder.Perform();
		TopoDS_Compound aResult = TopoDS::Compound(aBuilder.Shape());
		TopAbs::Print(aResult.ShapeType() , std::cout);
		std::cout << std::endl;

		TopExp_Explorer ex(aResult , TopAbs_SOLID);
		while (ex.More())
		{
			Handle(AIS_InteractiveObject) aisSPA = new MAisDemo(ex.Current());
			myContext->Display(aisSPA , 1 , 0 , false);

			ex.Next();
		}
	}
	else if (cbb_Boolean->currentText() == "BOA")
	{
		// BOPAlgo可更直观添加多个shape

		BOPAlgo_BOP aBuilder;
		// Setting arguments
		TopoDS_Shape aShape = BRepPrimAPI_MakeBox(100 , 100 , 200);
		std::vector< TopoDS_Shape> shapes = { { aShape} };
		TopTools_ListOfShape aLSObjects;
		for (auto& s : shapes)
		{
			aLSObjects.Append(s);
		}
		aBuilder.SetArguments(aLSObjects);

		TopoDS_Shape aT1 = BRepPrimAPI_MakeBox(gp_Pnt(50 , 50 , 100) , 100 , 100 , 50);
		TopoDS_Shape aT2 = BRepPrimAPI_MakeSphere(30);
		std::vector< TopoDS_Shape> tools = { { aT1,aT2} };
		TopTools_ListOfShape aLSTools;
		for (auto& s : tools)
		{
			aLSTools.Append(s);
		}
		aBuilder.SetTools(aLSTools);

		aBuilder.SetOperation(BOPAlgo_CUT);
		aBuilder.SetRunParallel(true);
		aBuilder.Perform();

		TopoDS_Shape aResult = aBuilder.Shape();
		TopAbs::Print(aResult.ShapeType() , std::cout);
		std::cout << std::endl;

		Handle(AIS_InteractiveObject) ais = new MAisDemo(aResult);
		myContext->Display(ais , 1 , 0 , false);
	}
	else if (cbb_Boolean->currentText() == "BRepAlgoAPI_Splitter")
	{
		BRepAlgoAPI_Splitter aBuilder;
		// Setting arguments
		TopoDS_Shape aShape = BRepPrimAPI_MakeSphere(50);
		std::vector< TopoDS_Shape> shapes = { { aShape } };
		TopTools_ListOfShape aLSObjects;
		for (auto& s : shapes)
		{
			aLSObjects.Append(s);
		}
		aBuilder.SetArguments(aLSObjects);

		TopoDS_Shape aFace = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , -10) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		TopoDS_Shape aFace1 = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , 10) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		TopoDS_Shape aFace2 = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0 , 0 , 40) , gp_Dir(0 , 0 , 1)) , -100 , 100 , -100 , 100);
		std::vector< TopoDS_Shape> tools = { { aFace,aFace1,aFace2 } };
		TopTools_ListOfShape aLSTools;
		for (auto& s : tools)
		{
			aLSTools.Append(s);
			Handle(AIS_InteractiveObject) aisF = new MAisDemo(s);
			aisF->SetTransparency(0.8);
			aisF->Attributes()->ShadingAspect()->SetColor(Quantity_NOC_BLUE);
			myContext->Display(aisF , 1 , 0 , false);
		}
		aBuilder.SetTools(aLSTools);

		aBuilder.SetRunParallel(true);
		aBuilder.Build();
		TopoDS_Compound aResult = TopoDS::Compound(aBuilder.Shape());
		TopAbs::Print(aResult.ShapeType() , std::cout);
		std::cout << std::endl;

		TopExp_Explorer ex(aResult , TopAbs_SOLID);
		while (ex.More())
		{
			Handle(AIS_InteractiveObject) aisSPA = new MAisDemo(ex.Current());
			myContext->Display(aisSPA , 1 , 0 , false);

			ex.Next();
		}
	}
	view_occt->fitAll();
}

void MainWindow::runHLR()
{
	if (cbb_HLR->currentText() == "HLRBRep_Algo")
	{
		TopoDS_Shape aCylinder = BRepPrimAPI_MakeCylinder(gp_Ax2(gp_Pnt() , gp_Dir(1 , 0 , 0)) , 10 , 100);
		TopoDS_Shape aCylinder1 = BRepPrimAPI_MakeCylinder(gp_Ax2(gp_Pnt(100 , 0 , 0) , gp_Dir(1 , 0 , 0)) , 20 , 25);
		BRepFilletAPI_MakeFillet  MFFillet(aCylinder1);
		TopExp_Explorer  exFillet(aCylinder1 , TopAbs_EDGE);
		double rFillet = 10.;
		MFFillet.Add(rFillet , TopoDS::Edge(exFillet.Current()));
		TopoDS_Shape aCylinderFillet = MFFillet.Shape();
		TopoDS_Shape aScrew = BRepAlgoAPI_Fuse(aCylinder , aCylinderFillet);

		Handle(AIS_InteractiveObject) aisScrew = new MAisDemo(aScrew);
		myContext->Display(aisScrew , 1 , 0 , false);

		Handle(HLRBRep_Algo) myAlgo = new HLRBRep_Algo();
		myAlgo->Add(aScrew , 1);
		HLRAlgo_Projector myProjector = HLRAlgo_Projector(gp_Ax2(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1)));
		myAlgo->Projector(myProjector);
		myAlgo->Update();
		myAlgo->Hide();

		HLRBRep_HLRToShape aHLRToShape(myAlgo);
		TopoDS_Shape VCompound = aHLRToShape.VCompound();
		TopoDS_Shape Rg1LineVCompound = aHLRToShape.Rg1LineVCompound();
		TopoDS_Shape RgNLineVCompound = aHLRToShape.RgNLineVCompound();
		TopoDS_Shape OutLineVCompound = aHLRToShape.OutLineVCompound();
		TopoDS_Shape IsoLineVCompound = aHLRToShape.IsoLineVCompound();
		TopoDS_Shape HCompound = aHLRToShape.HCompound();
		TopoDS_Shape Rg1LineHCompound = aHLRToShape.Rg1LineHCompound();
		TopoDS_Shape RgNLineHCompound = aHLRToShape.RgNLineHCompound();
		TopoDS_Shape OutLineHCompound = aHLRToShape.OutLineHCompound();
		TopoDS_Shape IsoLineHCompound = aHLRToShape.IsoLineHCompound();
		std::vector<TopoDS_Shape> shapes = { VCompound,Rg1LineVCompound,RgNLineVCompound ,OutLineVCompound,IsoLineVCompound,
		HCompound ,Rg1LineHCompound, RgNLineHCompound ,OutLineHCompound ,IsoLineHCompound };
		std::vector<std::string> types =
		{ "VCompoun","Rg1LineVCompound" ,"RgNLineVCompound" ,"OutLineVCompound" ,"IsoLineVCompound" ,
			"HCompound","Rg1LineHCompound" ,"RgNLineHCompound" ,"OutLineHCompound" ,"IsoLineHCompound"
		};
		int distance = 100;
		int i = 0;
		gp_Trsf T;
		for (auto s : shapes)
		{
			if (!s.IsNull())
			{
				T.SetTranslation(gp_Vec(0 , distance , 0));
				BRepBuilderAPI_Transform trsf(s , T);
				Handle(AIS_InteractiveObject) ais = new MAisDemo(trsf.Shape());
				myContext->Display(ais , 1 , 0 , false);
			}

			Handle(AIS_TextLabel) aisText = new AIS_TextLabel();
			aisText->SetText(types[i].c_str());
			aisText->SetPosition(gp_Pnt(250 , distance , 0));
			myContext->Display(aisText , 0 , 0 , false);

			++i;
			distance += 100;
		}
	}
	
	view_occt->fitAll();
}

void MainWindow::runDataExchange()
{
	if (cbb_DataExchange->currentText() == "ExportBrep")
	{

	}
	else if (cbb_DataExchange->currentText() == "ImportBrep")
	{

	}
	else if (cbb_DataExchange->currentText() == "ExportStep")
	{
		std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/step/testStep.step";

		DataExchange dx;
		dx.setAisObjs(objs);
		dx.ExportStep(filePath.c_str());
	}
	else if (cbb_DataExchange->currentText() == "ImportStep")
	{
		std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/step/linkrods.step";
		//std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/step/screw.step";

		DataExchange dx;
		dx.ImportStep(filePath.c_str());
		objs = dx.getAisObjs();

		for (auto e : objs)
		{
			myContext->Display(e , 1 , 0 , false);
		}
	}
	else if (cbb_DataExchange->currentText() == "ExportIges")
	{
		std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/step/testIges.iges";

		DataExchange dx;
		dx.setAisObjs(objs);
		dx.ExportIges(filePath.c_str());
	}
	else if (cbb_DataExchange->currentText() == "ImportIges")
	{
		//std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/iges/bearing.iges";
		std::string filePath = "E:/8other/CppLearn/OCCTTutorial/models/iges/hammer.iges";

		DataExchange dx;
		dx.ImportIges(filePath.c_str());
		objs = dx.getAisObjs();

		for (auto e : objs)
		{
			myContext->Display(e , 1 , 0 , false);
		}
	}
	else if (cbb_DataExchange->currentText() == "ExportObj")
	{

	}
	else if (cbb_DataExchange->currentText() == "ImportObj")
	{
		std::string filePath = "E:/other/CppLearn/OCCTTutorial/models/obj/gundam.obj";

		DataExchange dx;
		dx.ImportObj(filePath.c_str());
		objs = dx.getAisObjs();

		for (auto e : objs)
		{
			myContext->Display(e , 1 , 0 , false);
		}
	}

	view_occt->fitAll();
}

void MainWindow::runAis()
{
	if (cbb_ais->currentText() == "HLR")
	{
		TopoDS_Shape aBox = BRepPrimAPI_MakeBox(100 , 100 , 200);
		Handle(AIS_InteractiveObject) ais = new myPk_IShape(aBox , PrsMgr_TOP_AllView);
		myContext->Display(ais , 1 , 0 , false);
		//ais->computeHlrPresentation();
	}
	else if (cbb_ais->currentText() == "setLocation")
	{
		TopoDS_Shape aBox = BRepPrimAPI_MakeBox(100 , 100 , 200);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aBox);
		myContext->Display(ais , 1 , 0 , false);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 300 , 0));
		TopLoc_Location L = TopLoc_Location(T);
		myContext->SetLocation(ais , L);
	}
	else if (cbb_ais->currentText() == "ObjectHierarchy")
	{
		TopoDS_Shape aBox = BRepPrimAPI_MakeBox(100 , 100 , 200);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(aBox);
		myContext->Display(ais , 1 , 0 , false);
		TopoDS_Shape aBox1 = BRepPrimAPI_MakeBox(gp_Pnt(100 , 0 , 0) , 100 , 100 , 200);
		Handle(AIS_InteractiveObject) ais1 = new MAisDemo(aBox1);
		myContext->Display(ais1 , 1 , 0 , false);
		TopoDS_Shape aBox2 = BRepPrimAPI_MakeBox(100 , 100 , 200);
		Handle(AIS_InteractiveObject) ais2 = new MAisDemo(aBox2);
		myContext->Display(ais2 , 1 , 0 , false);
		ais1->AddChild(ais);
		gp_Trsf T;
		T.SetTranslation(gp_Vec(0 , 300 , 0));
		TopLoc_Location L = TopLoc_Location(T);
		myContext->SetLocation(ais1 , L);
	}
	else if (cbb_ais->currentText() == "Fitter")
	{
		TopoDS_Shape theShape = BRepPrimAPI_MakeCylinder(10 , 20);
		Handle(AIS_InteractiveObject) aShapePrs = new MAisDemo(theShape);
		myContext->Display(aShapePrs , AIS_Shaded , 0 , true , true);

		int aSubShapeSelMode = MAisDemo::SelectionMode(TopAbs_FACE);
		myContext->Activate(aShapePrs , aSubShapeSelMode);

		//Handle(StdSelect_FaceFilter) aFil1 = new StdSelect_FaceFilter(StdSelect_Revol);
		//myContext->AddFilter(aFil1);
		Handle(StdSelect_FaceFilter) aFil2 = new StdSelect_FaceFilter(StdSelect_Plane);
		myContext->AddFilter(aFil2);
	}
	else if (cbb_ais->currentText() == "Selection/Capture")
	{
		for (myContext->InitSelected(); myContext->MoreSelected(); myContext->NextSelected())
		{
			// 两者等同
			//Handle(AIS_InteractiveObject) anObj = myContext->SelectedInteractive();
			//Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());

			Handle(SelectMgr_EntityOwner) anOwner = myContext->SelectedOwner();
			// 如果选择的是个端点
			if (Handle(MCaptureOwnerEndPonit) aEndPonitOwner = Handle(MCaptureOwnerEndPonit)::DownCast(anOwner))
			{
				std::cout << aEndPonitOwner->getPonit() << std::endl;
			}
		}
	}

	view_occt->fitAll();
}

void MainWindow::runStdAis()
{
	if (cbb_stdAis->currentText() == "Datum")
	{
		Handle(Geom_CartesianPoint) aGeoPnt = new Geom_CartesianPoint(50 , 50 , 0);
		Handle(AIS_InteractiveObject) ais = new AIS_Point(aGeoPnt);
		// 只有线框模式
		myContext->Display(ais , 0 , 0 , false);

		gp_Ax1 ax1 = gp_Ax1(gp_Pnt(100 , 0 , 0) , gp_Dir(0 , 0 , 1));
		Handle(AIS_InteractiveObject) aisAxi = new AIS_Axis(ax1);
		myContext->Display(aisAxi , 0 , 0 , false);

		Handle(Geom_Line) aGeoLine = new Geom_Line(gp_Pnt(0 , 100 , 0) , gp_Dir(0 , 1 , 0));
		// infinite
		Handle(AIS_InteractiveObject) aisLine = new AIS_Line(aGeoLine);
		myContext->Display(aisLine , 0 , 0 , false);

		gp_Ax2 ax2 = gp_Ax2(gp_Pnt(200 , 0 , 0) , gp_Dir(1 , 0 , 0));
		Handle(Geom_Circle) aGeoCircle = new Geom_Circle(ax2 , 50);
		Handle(AIS_InteractiveObject) aisCircle = new AIS_Circle(aGeoCircle);
		myContext->Display(aisCircle , 0 , 0 , false);

		Handle(Geom_Plane) aGeoPlane = new Geom_Plane(gp_Pnt(200 , 0 , 0) , gp_Dir(0 , 0 , 1));
		// 需设置中心点，不然shade模式位置错误
		Handle(AIS_InteractiveObject) aisPlane = new AIS_Plane(aGeoPlane , gp_Pnt(200 , 0 , 0));
		myContext->Display(aisPlane , 1 , 0 , false);

		gp_Ax2 ax22 = gp_Ax2(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		Handle(Geom_Axis2Placement) aGeoAxis2Placement = new Geom_Axis2Placement(ax22);
		Handle(AIS_Trihedron) aisTrihedron = new AIS_Trihedron(aGeoAxis2Placement);
		// 显示模式在此设置，display方法报错
		aisTrihedron->SetDatumDisplayMode(Prs3d_DM_Shaded);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_XArrow , Quantity_NOC_RED2);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_YArrow , Quantity_NOC_GREEN2);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_ZArrow , Quantity_NOC_BLUE2);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_XAxis , Quantity_NOC_RED2);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_YAxis , Quantity_NOC_GREEN2);
		aisTrihedron->SetDatumPartColor(Prs3d_DP_ZAxis , Quantity_NOC_BLUE2);
		myContext->Display(aisTrihedron , 0 , AIS_TrihedronSelectionMode_Axes , false);

		Handle(AIS_PlaneTrihedron) aisPlaneTrihedron = new AIS_PlaneTrihedron(aGeoPlane);
		aisPlaneTrihedron->SetLength(100);
		myContext->Display(aisPlaneTrihedron , 0 , 0 , false);

	}
	else if (cbb_stdAis->currentText() == "AIS_PointCloud")
	{
		Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints(2000 , true);
		aPoints->AddVertex(gp_Pnt(-40.0 , -40.0 , -40.0) , Quantity_Color(Quantity_NOC_BLUE1));
		aPoints->AddVertex(gp_Pnt(40.0 , 40.0 , 40.0) , Quantity_Color(Quantity_NOC_BLUE2));

		Handle(AIS_PointCloud) aPntCloud = new AIS_PointCloud();
		aPntCloud->SetPoints(aPoints);
		myContext->Display(aPntCloud , 0 , 0 , false);
	}
	else if (cbb_stdAis->currentText() == "Relations")
	{
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 0 , 0) , gp_Pnt(0 , 100 , 0));
		TopoDS_Edge aEdge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(200 , 0 , 0) , gp_Pnt(200 , 100 , 0));
		TopoDS_Edge aEdge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 100 , 0) , gp_Pnt(100 , 100 , 0));
		Handle(AIS_InteractiveObject) aisEdge = new AIS_Shape(aEdge);
		Handle(AIS_InteractiveObject) aisEdge1 = new AIS_Shape(aEdge1);
		Handle(AIS_InteractiveObject) aisEdge2 = new AIS_Shape(aEdge2);
		myContext->Display(aisEdge , 0 , 0 , false);
		myContext->Display(aisEdge1 , 0 , 0 , false);
		myContext->Display(aisEdge2 , 0 , 0 , false);

		Handle(Geom_Plane) aGeoPlane = new Geom_Plane(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		Handle(PrsDim_ParallelRelation) aisParallel = new PrsDim_ParallelRelation(aEdge , aEdge1 , aGeoPlane);
		myContext->Display(aisParallel , 0 , 0 , false);
		// 不垂直也会显示歪的标记
		Handle(PrsDim_PerpendicularRelation) aisPerpendicular = new PrsDim_PerpendicularRelation(aEdge , aEdge2 , aGeoPlane);
		myContext->Display(aisPerpendicular , 0 , 0 , false);
	}
	else if (cbb_stdAis->currentText() == "Dimensions")
	{
		TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(gp_Pnt(0 , 0 , 0) , gp_Pnt(0 , 100 , 0));
		Handle(AIS_InteractiveObject) aisEdge = new AIS_Shape(aEdge);
		myContext->Display(aisEdge , 0 , 0 , false);
		gp_Pln aPln = gp_Pln(gp_Pnt(0 , 0 , 0) , gp_Dir(0 , 0 , 1));
		Handle(PrsDim_LengthDimension) aisLength = new PrsDim_LengthDimension(aEdge , aPln);
		myContext->Display(aisLength , 0 , 0 , false);
	}
	view_occt->fitAll();
}

void MainWindow::runGraphic3d()
{
	if (cbb_Graphic3d->currentText() == "Primitive arrays")
	{
		Handle(AIS_InteractiveObject) ais = new MAisObject7();
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_Graphic3d->currentText() == "Text primitive")
	{
		Handle(AIS_InteractiveObject) ais = new MAisObject8();
		myContext->Display(ais , 0 , 0 , false);
	}
	else if (cbb_Graphic3d->currentText() == "Clipping planes")
	{
		Standard_Integer aMaxClipPlanes = myViewer->Driver()->InquireLimit(Graphic3d_TypeOfLimit_MaxNbClipPlanes);
		std::cout << aMaxClipPlanes << std::endl;

		TopoDS_Shape box = BRepPrimAPI_MakeBox(200 , 400 , 800);
		Handle(AIS_InteractiveObject) ais = new MAisDemo(box);
		myContext->Display(ais , 1 , 0 , false);

		gp_Pln aPln = gp_Pln(gp_Pnt(0 , 0 , 35) , gp_Dir(0 , 0 , 1));
		Handle(Graphic3d_ClipPlane) aClipPlane = new Graphic3d_ClipPlane(aPln);
		gp_Pln aPln1 = gp_Pln(gp_Pnt(0 , 0 , 110) , gp_Dir(0 , 0 , -1));
		Handle(Graphic3d_ClipPlane) aClipPlane1 = new Graphic3d_ClipPlane(aPln1);
		//aClipPlane->SetCapping(true);
		//aClipPlane->SetOn(false);
		//aClipPlane1->SetOn(false);
		view_occt->getView()->AddClipPlane(aClipPlane);
		view_occt->getView()->AddClipPlane(aClipPlane1);

	}

	view_occt->fitAll();
}

void MainWindow::runMShape()
{
	if (cbb_MShape->currentText() == "PipeFitting")
	{
		std::vector<gp_Pnt> pnts = { gp_Pnt(0 , 0 , 0) ,gp_Pnt(100 , 0 , 0) };
		std::shared_ptr< MSLinearRect> p = std::make_shared< MSLinearRect>(pnts);

		std::vector<gp_Pnt> pnts1 = { gp_Pnt(100 , 0 , 0) ,gp_Pnt(200 , 200 , 0) };
		std::shared_ptr< MSLinearRect> p1 = std::make_shared< MSLinearRect>(pnts1);

		std::vector<gp_Pnt> pnts2 = { gp_Pnt(200 , 200 , 0) ,gp_Pnt(300 , 200 , 0) };
		std::shared_ptr< MSLinearRect> p2 = std::make_shared< MSLinearRect>(pnts2 , 40 , 20 , "");

		std::vector<gp_Pnt> pnts3 = { gp_Pnt(300 , 200 , 0) ,gp_Pnt(500 , 200 , 150) };
		std::shared_ptr< MSLinearRect> p3 = std::make_shared< MSLinearRect>(pnts3);

		std::shared_ptr< MSPipeFitting> pipe = std::make_shared< MSPipeFitting>(p , p1);
		std::shared_ptr< MSPipeFitting> pipe1 = std::make_shared< MSPipeFitting>(p1 , p2);
		std::shared_ptr< MSPipeFitting> pipe2 = std::make_shared< MSPipeFitting>(p2 , p3);

		std::vector< std::shared_ptr< MSAbstract>> ps = { p,pipe,p1,pipe1,p2,pipe2,p3 };
		for (auto e : ps)
		{
			TopoDS_Shape s = e->getShape();
			Handle(AIS_InteractiveObject) ais = new MAisDemo(s);
			myContext->Display(ais , 1 , 0 , false);

			TopoDS_Shape path = e->getPath();
			Handle(AIS_InteractiveObject) aisPath = new MAisDemo(path);
			myContext->Display(aisPath , 1 , 0 , false);
		}
	}
	view_occt->fitAll();
}

bool MainWindow::eventFilter(QObject* watched , QEvent* event)
{
	if (event->type() == QEvent::MouseMove)
	{
		QMouseEvent* theEvent = static_cast<QMouseEvent*>(event);
		Qt::MouseButtons aMouseButtons = theEvent->buttons();
		myClickPos = { _devPx * theEvent->pos().x() , _devPx * theEvent->pos().y() };
		updateStatusBar(myClickPos);
	}

	return QMainWindow::eventFilter(watched , event);
}

Handle(V3d_Viewer) MainWindow::Viewer(const V3d_TypeOfOrientation theViewProj)
{
	static Handle(OpenGl_GraphicDriver) aGraphicDriver;
	Handle(Aspect_DisplayConnection) aDisplayConnection;
	aGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection);
	Handle(V3d_Viewer) aViewer = new V3d_Viewer(aGraphicDriver);
	aViewer->SetDefaultViewProj(theViewProj);

	aViewer->SetDefaultLights();
	aViewer->SetLightOn();
	return aViewer;
}

void MainWindow::updateStatusBar(const std::vector<double>& aNewPos)
{
	double XScreen = aNewPos[0];
	double YScreen = aNewPos[1];

	double x , y , z;
	view_occt->getView()->Convert(XScreen , YScreen , x , y , z);
	gp_Pnt worldPnt = gp_Pnt(x , y , z);

	double xEye , yEye , zEye , xAt , yAt , zAt;
	view_occt->getView()->Eye(xEye , yEye , zEye);
	view_occt->getView()->At(xAt , yAt , zAt);
	gp_Pnt eyePoint(xEye , yEye , zEye);
	gp_Pnt atPoint(xAt , yAt , zAt);

	gp_Dir eyeDir(gp_Vec(eyePoint , atPoint));
	gp_Pln plnAt = gp_Pln(atPoint , eyeDir);

	Handle(Geom_Plane) geoPlane = new Geom_Plane(plnAt);
	GeomAPI_ProjectPointOnSurf project(worldPnt , geoPlane);
	gp_Pnt position = project.NearestPoint();


	// 同上
	//gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(plnAt , worldPnt);
	//gp_Pnt position1 = ElSLib::Value(ConvertedPointOnPlane.X() , ConvertedPointOnPlane.Y() , plnAt);
	//QString positionInfo1 = QString("Position: %0, %1, %2").arg(position1.X()).arg(position1.Y()).arg(position1.Z());

	//QString screenPntInfo = QString("Screen: %0, %1").arg(XScreen).arg(YScreen);
	//QString worldPntInfo = QString("World: %0, %1, %2").arg(x).arg(y).arg(z);
	//QString eyePntInfo = QString("Eye: %0, %1, %2").arg(xEye).arg(yEye).arg(zEye);
	//QString atPntInfo = QString("At: %0, %1, %2").arg(xAt).arg(yAt).arg(zAt);
	QString positionInfo = QString("WCS: %0, %1, %2").arg(position.X()).arg(position.Y()).arg(position.Z());
	//QString info = screenPntInfo + "  "  + positionInfo;
	lb_positionInfo->setText(positionInfo);
}
